うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】SceneView のカメラから GUI Rect の座標を取得する

[ExecuteAlways]
public class SampleMonoBehaviour : MonoBehaviour
{
    private void OnEnable()
    {
        SceneView.duringSceneGui += SceneGUI;
    }

    private void SceneGUI(SceneView sceneView)
    {
        var pos = sceneView.camera.WorldToViewportPoint(transform.position);
        Handles.BeginGUI();
        GUI.Label(new Rect(pos, new Vector2(100, 12)), "test");
        Handles.EndGUI();
    }
}

上記のように、sceneView のカメラから Viewport座標を取得しても正しい位置に表示されない

それもそのはずで、GUI の描画に利用してるのは Viewport座標を利用していないため、

Window のサイズに合わせて適切に変換してあげる必要がある

その変換処理が以下

public static class SceneViewHelper
{
    /// <summary>
    /// WorldToViewportPoint は Toolbar のサイズを考慮していないため考慮して計算する
    /// </summary>
    public static Vector3 SceneViewWorldToScreenPoint(SceneView sceneView, Vector2 worldPosition)
    {
        var pointInView = sceneView.camera.WorldToViewportPoint(worldPosition);
        var screenPosition = pointInView * sceneView.position.size;
        screenPosition.y = sceneView.position.height - screenPosition.y;
 
        return screenPosition;
    }
}

これを利用して先程の処理を書き換えるとこうなる

    private void SceneGUI(SceneView sceneView)
    {
        var pos = SceneViewHelper.SceneViewWorldToScreenPoint(sceneView, transform.position);
        Handles.BeginGUI();
        GUI.Label(new Rect(pos, new Vector2(100, 12)), "test");
        Handles.EndGUI();
    }

これで正しい位置に表示させることができる