Unity Camera WorldToScreenPoint ๊ฐ€์ด๋“œ

WorldToScreenPoint๋Š” 3D ์›”๋“œ ์ขŒํ‘œ๋ฅผ 2D ์Šคํฌ๋ฆฐ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋‹ค. UI๋ฅผ 3D ์˜ค๋ธŒ์ ํŠธ ์œ„์น˜์— ๋งž์ถœ ๋•Œ ์“ด๋‹ค!

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

public Vector3 Camera.WorldToScreenPoint(Vector3 position);
  • ์ž…๋ ฅ: ์›”๋“œ ์ขŒํ‘œ (Vector3)
  • ์ถœ๋ ฅ: ์Šคํฌ๋ฆฐ ์ขŒํ‘œ (Vector3)
    • x, y: ํ™”๋ฉด ํ”ฝ์…€ ์ขŒํ‘œ
    • z: ์นด๋ฉ”๋ผ๋กœ๋ถ€ํ„ฐ์˜ ๊ฑฐ๋ฆฌ (0๋ณด๋‹ค ์ž‘์œผ๋ฉด ์นด๋ฉ”๋ผ ๋’ค)

์ขŒํ‘œ๊ณ„ ์ดํ•ด

์›”๋“œ ์ขŒํ‘œ

  • ์œ ๋‹ˆํ‹ฐ์˜ 3D ๊ณต๊ฐ„ ์ขŒํ‘œ
  • ์›์  (0,0,0) ๊ธฐ์ค€
  • ์˜ˆ: (5, 10, 0)

์Šคํฌ๋ฆฐ ์ขŒํ‘œ

  • ํ™”๋ฉด ํ”ฝ์…€ ์ขŒํ‘œ
  • ์ขŒํ•˜๋‹จ (0, 0), ์šฐ์ƒ๋‹จ (Screen.width, Screen.height)
  • ์˜ˆ: 1920x1080 ํ™”๋ฉด์—์„œ (960, 540) = ํ™”๋ฉด ์ค‘์•™

๊ธฐ๋ณธ ์˜ˆ์‹œ

using UnityEngine;

public class WorldToScreenExample : MonoBehaviour
{
    public Camera mainCamera;
    public Transform targetObject;

    void Update()
    {
        Vector3 screenPos = mainCamera.WorldToScreenPoint(targetObject.position);
        Debug.Log($"์Šคํฌ๋ฆฐ ์ขŒํ‘œ: {screenPos}");
    }
}

๋ทฐํฌํŠธ ์ขŒํ‘œ vs ์Šคํฌ๋ฆฐ ์ขŒํ‘œ

  • ๋ทฐํฌํŠธ ์ขŒํ‘œ: (0,0) ~ (1,1) ๋ฒ”์œ„๋กœ ํ‘œํ˜„
  • ์Šคํฌ๋ฆฐ ์ขŒํ‘œ: ํ”ฝ์…€ ๋‹จ์œ„

๋ฉ”์†Œ๋“œ:

  • WorldToScreenPoint: ์›”๋“œ โ†’ ์Šคํฌ๋ฆฐ
  • WorldToViewportPoint: ์›”๋“œ โ†’ ๋ทฐํฌํŠธ

ํ™œ์šฉ ์˜ˆ์‹œ

3D ์˜ค๋ธŒ์ ํŠธ ์œ„์— UI๋ฅผ ํ‘œ์‹œํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค:

using UnityEngine;
using UnityEngine.UI;

public class WorldUI : MonoBehaviour
{
    public Camera mainCamera;
    public Transform targetTransform;
    public RectTransform uiElement;

    void Update()
    {
        // ์›”๋“œ ์ขŒํ‘œ๋ฅผ ์Šคํฌ๋ฆฐ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜
        Vector3 screenPos = mainCamera.WorldToScreenPoint(targetTransform.position);

        // ์นด๋ฉ”๋ผ ์•ž์— ์žˆ์„ ๋•Œ๋งŒ ํ‘œ์‹œ
        if (screenPos.z > 0)
        {
            uiElement.gameObject.SetActive(true);
            uiElement.position = screenPos;
        }
        else
        {
            uiElement.gameObject.SetActive(false);
        }
    }
}

์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์‹œ

private void LateUpdate()
{
    if (targetTransform == null)
    {
        Destroy(gameObject);
        return;
    }

    // ์›”๋“œ ์ขŒํ‘œ โ†’ ์Šคํฌ๋ฆฐ ์ขŒํ‘œ ๋ณ€ํ™˜
    Vector3 screenPosition = Camera.main.WorldToScreenPoint(targetTransform.position);

    // UI๋ฅผ ์Šคํฌ๋ฆฐ ์ขŒํ‘œ + distance ์œ„์น˜์— ๋ฐฐ์น˜
    rectTransform.position = screenPosition + distance;
}

LateUpdate ์‚ฌ์šฉ ์ด์œ : ์˜ค๋ธŒ์ ํŠธ ์œ„์น˜๊ฐ€ Update์—์„œ ๊ฐฑ์‹ ๋œ ํ›„ UI ์œ„์น˜๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ๋งž์ถ”๊ธฐ ์œ„ํ•จ

์ •๋ฆฌ

WorldToScreenPoint๋Š” 3D ์˜ค๋ธŒ์ ํŠธ๋ฅผ 2D UI์™€ ์—ฐ๊ฒฐํ•  ๋•Œ ํ•„์ˆ˜๋‹ค. ์ฒด๋ ฅ ๋ฐ”, ํ€˜์ŠคํŠธ ๋งˆ์ปค, ์กฐ์ค€์„  ๋“ฑ์— ์œ ์šฉํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค!