RectTransformの重なり判定とは?
UIを作っていると、2つのUI要素が重なっているかどうかを判定したい場面があります。
たとえば以下のようなケースです。
- ドラッグ&ドロップで、アイテムをスロットに重ねたときの判定
- UI同士が重なっていないかのチェック
- 特定のエリアにUI要素が入ったかどうかの検出
こうした判定は、RectTransformの矩形情報を使えば実現できます。
GetWorldCornersで矩形を取得する
RectTransformの矩形情報を取得するには、GetWorldCorners()を使います。
このメソッドは、矩形の四隅のワールド座標をVector3の配列に格納します。
var corners = new Vector3[4];
rectTransform.GetWorldCorners(corners);
取得される4つの角は、以下の順番で格納されます。
- corners[0] … 左下
- corners[1] … 左上
- corners[2] … 右上
- corners[3] … 右下

返ってくるのはワールド座標です。
ローカル座標ではないので、親のTransformによるスケールや回転の影響を受けた後の値が返ります。
Rect.Overlapsで重なりを判定する
2つのRectTransformが重なっているかどうかは、Rect.Overlaps()で判定できます。
Rect.Overlaps()は、2つのRectが重なっていればtrueを返すメソッドです。
GetWorldCornersからRectを作る
GetWorldCorners()で取得した座標からRectを作り、Overlaps()に渡します。
以下のようなヘルパーメソッドを用意すると便利です。
using UnityEngine;
public static class RectTransformOverlapHelper
{
private static readonly Vector3[] _cornersA = new Vector3[4];
private static readonly Vector3[] _cornersB = new Vector3[4];
/// <summary>
/// 2つのRectTransformが重なっているかどうかを判定する
/// </summary>
public static bool Overlaps(RectTransform rectA, RectTransform rectB)
{
rectA.GetWorldCorners(_cornersA);
rectB.GetWorldCorners(_cornersB);
var rectAWorld = ToRect(_cornersA);
var rectBWorld = ToRect(_cornersB);
return rectAWorld.Overlaps(rectBWorld);
}
/// <summary>
/// GetWorldCornersの結果からRectを生成する
/// </summary>
private static Rect ToRect(Vector3[] corners)
{
// corners[0]が左下、corners[2]が右上
var min = corners[0];
var max = corners[2];
return new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
}
}
使い方はシンプル。
using UnityEngine;
public class OverlapChecker : MonoBehaviour
{
[SerializeField] private RectTransform _targetA;
[SerializeField] private RectTransform _targetB;
private void Update()
{
if (RectTransformOverlapHelper.Overlaps(_targetA, _targetB))
{
Debug.Log("重なっています");
}
}
}
Canvas Render Modeごとの挙動
GetWorldCorners()はワールド座標を返すため、CanvasのRender Modeによって値のスケールが変わります。
Screen Space - Overlayの場合、ワールド座標がスクリーン座標に近い値になるので直感的に扱いやすいです。
Screen Space - CameraやWorld Spaceの場合は、カメラとの距離や配置によってワールド座標の値が変わります。
ただし、同じCanvas内のUI同士であれば座標系は同じなので、Overlaps()の比較は問題なく動きます。
異なるCanvas間で比較するときは座標系が異なるため、注意してください。
RectTransformUtility.RectangleContainsScreenPointとの使い分け
似たような判定として、RectTransformUtility.RectangleContainsScreenPoint()があります。
こちらは「ある点がRectTransformの矩形内にあるか」を判定するメソッドです。
// マウス座標がRectTransformの範囲内にあるかどうか
bool isInside = RectTransformUtility.RectangleContainsScreenPoint(
rectTransform,
Input.mousePosition,
camera
);
用途が違うので、以下のように使い分けます。
- 矩形同士の重なり →
GetWorldCorners()+Rect.Overlaps() - 点が矩形内にあるか →
RectTransformUtility.RectangleContainsScreenPoint()
マウスやタッチの座標とUIの当たり判定ならRectangleContainsScreenPoint()、UI同士の重なりならRect.Overlaps()です。
まとめ
RectTransform同士の重なり判定は、GetWorldCorners()で四隅を取得してRectに変換し、Rect.Overlaps()で比較するのが手軽です。
同じCanvas内であればRender Modeを問わず動くので、ドラッグ&ドロップや重複チェックなど色々な場面で使えます。
「点がUI内にあるか」ならRectangleContainsScreenPoint()など、目的に応じて使い分けてみてください。