はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】RectTransformのCorners(四隅)のスクリーン座標を取得する(RenderModeにより変化)

はじめに

RectTransformCorners(角)の座標のスクリーン座標を取得しようと思ったところ少し手間取ったので書き残しておきたいと思います。

私が調べた限りCanvasRenderModeによって動作が異なるようなので、それぞれについて書きます。

また原因が異なる可能性も大いにある(誤った情報を書いてしまった場合は恐縮です)ので、もし間違っている場合はご指摘いただけると嬉しいです。

CanvasのRenderModeが「Screen Space - Overlay」

f:id:hanaaaaaachiru:20220403215532p:plain
Screen Space - Overlay

RectTransformの四隅のワールド座標を取得

RectTransform.GetWorldCornersメソッドを利用することで、RectTransformの長方形の角の座標を取得することができます。
docs.unity3d.com

var rectTransform = GetComponent<RectTransform>();

// ワールド空間におけるRectTransformの長方形の角の座標を取得
// 返される4つの頂点は時計回りに「左下,左上,右上,右下」
var corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);

for (var i = 0; i < corners.Length; i++)
{
    // 例
    // Screen Corners[0] : (1185.0, 418.0, 0.0)
    // Screen Corners[1] : (1185.0, 918.0, 0.0)
    // Screen Corners[2] : (1685.0, 918.0, 0.0)
    // Screen Corners[3] : (1685.0, 418.0, 0.0)
    Debug.Log($"World Corners[{i}] : {corners[i]}");
}

CanvasRenderModeScreen Space - Overlayの場合は、RectTransform.GetWorldCornersメソッドの返り値がそのままスクリーン座標になっているようでした。

f:id:hanaaaaaachiru:20220403215303p:plain
スクリーン座標

CanvasのRenderModeが「Screen Space - Camera」

f:id:hanaaaaaachiru:20220403215602p:plain
Screen Space - Camera

RectTransformの四隅のワールド座標を取得

同様にRectTransform.GetWorldCornersメソッドを利用することで、RectTransformの長方形の角の座標を取得します。
docs.unity3d.com

var rectTransform = GetComponent<RectTransform>();

// ワールド空間におけるRectTransformの長方形の角の座標を取得
// 返される4つの頂点は時計回りに「左下,左上,右上,右下」
var corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);

for (var i = 0; i < corners.Length; i++)
{
    // 例
    // World Corners[0] : (0.2, 0.9, -9.0)
    // World Corners[1] : (0.2, 1.4, -9.0)
    // World Corners[2] : (0.8, 1.4, -9.0)
    // World Corners[3] : (0.8, 0.9, -9.0)
    Debug.Log($"World Corners[{i}] : {corners[i]}");
}

ただこちらで取得できる座標はスクリーン座標にはならないので、加工が必要になります。

(余談)ローカル座標を取得

またRectTransform.GetLocalCornersメソッドというRectTransform.GetWorldCornersのローカル座標バージョンもあります。

docs.unity3d.com

var rectTransform = GetComponent<RectTransform>();

// ローカル空間におけるRectTransformの長方形の角の座標を取得
// 返される4つの頂点は時計回りに「左下,左上,右上,右下」
var corners = new Vector3[4];
rectTransform.GetLocalCorners(corners);

for (var i = 0; i < corners.Length; i++)
{
    // 例
    // Local Corners[0] : (-250.0, -250.0, 0.0)
    // Local Corners[1] : (-250.0, 250.0, 0.0)
    // Local Corners[2] : (250.0, 250.0, 0.0)
    // Local Corners[3] : (250.0, -250.0, 0.0)
    Debug.Log($"Local Corners[{i}] : {corners[i]}");
}

スクリーン座標に変換する

スクリーン座標とは画面の左下を(0, 0)、右上を(Screen.Width, Screen.Height)とした座標系のことですね。

RectTransformの四隅の座標をスクリーン座標で取得するAPIはないので、ワールド座標からスクリーン座標への変換をしてあげることで解決します。

やり方は簡単で、RectTransformUtility.WorldToScreenPointメソッドを利用すればOKです。
docs.unity3d.com

var rectTransform = GetComponent<RectTransform>();

// ローカル空間におけるRectTransformの長方形の角の座標を取得
// 返される4つの頂点は時計回りに「左下,左上,右上,右下」
var corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);

for (var i = 0; i < corners.Length; i++)
{
    // ワールド座標からスクリーン座標へ変換
    corners[i] = RectTransformUtility.WorldToScreenPoint(Camera.main, corners[i]);
            
    // 例
    // Screen Corners[0] : (1185.0, 418.0, 0.0)
    // Screen Corners[1] : (1185.0, 918.0, 0.0)
    // Screen Corners[2] : (1685.0, 918.0, 0.0)
    // Screen Corners[3] : (1685.0, 418.0, 0.0)
    Debug.Log($"Screen Corners[{i}] : {corners[i]}");
}
f:id:hanaaaaaachiru:20220403215303p:plain
スクリーン座標

CanvasのRenderModeが「World Space」

f:id:hanaaaaaachiru:20220403215639p:plain
World Space

スクリーン座標を取得する

CanvasRenderModeWorld Spaceの場合は、RectTransformUtility.WorldToScreenPointを利用します。

var rectTransform = GetComponent<RectTransform>();

// ローカル空間におけるRectTransformの長方形の角の座標を取得
// 返される4つの頂点は時計回りに「左下,左上,右上,右下」
var corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);

for (var i = 0; i < corners.Length; i++)
{
    // ワールド座標からスクリーン座標へ変換
    corners[i] = RectTransformUtility.WorldToScreenPoint(Camera.main, corners[i]);
            
    // 例
    // Screen Corners[0] : (1185.0, 418.0, 0.0)
    // Screen Corners[1] : (1185.0, 918.0, 0.0)
    // Screen Corners[2] : (1685.0, 918.0, 0.0)
    // Screen Corners[3] : (1685.0, 418.0, 0.0)
    Debug.Log($"Screen Corners[{i}] : {corners[i]}");
}
f:id:hanaaaaaachiru:20220403215303p:plain
スクリーン座標