うにてぃブログ

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

【Unity】特定の RectTransform の範囲内かどうか判定する

RectTransform から Bounds を取得し、Bounds を用いて判定を行うことで範囲内かどうか知ることができます

RectTransformUtility.CalculateRelativeRectTransformBounds を利用することで Bounds が取得できますが、
これは子供の RectTransfrom も対象にしているため利用できませんでした

RectTransform の範囲内に 指定の座標があるかどうか

f:id:hacchi_man:20200502225905g:plain

RectTransform の範囲内に RectTransform があるかどうか

f:id:hacchi_man:20200502225615g:plain

using UnityEngine;
using UnityEngine.EventSystems;
 
public static class RectTransformExtension
{
    private static readonly Vector3[] s_Corners = new Vector3[4];
    
    public static bool Contains(this RectTransform self, PointerEventData eventData)
    {
        var selfBounds = GetBounds(self);
        var worldPos = Vector3.zero;
        RectTransformUtility.ScreenPointToWorldPointInRectangle(
            self,
            eventData.position,
            eventData.pressEventCamera,
            out worldPos);
        worldPos.z = 0f;

        return selfBounds.Contains(worldPos);
    }
 
    public static bool Contains(this RectTransform self, RectTransform target)
    {
        var selfBounds = GetBounds(self);
        var targetBounds = GetBounds(target);

        return selfBounds.Contains(new Vector3(targetBounds.min.x, targetBounds.min.y, 0f)) &&
               selfBounds.Contains(new Vector3(targetBounds.max.x, targetBounds.max.y, 0f)) &&
               selfBounds.Contains(new Vector3(targetBounds.min.x, targetBounds.max.y, 0f)) &&
               selfBounds.Contains(new Vector3(targetBounds.max.x, targetBounds.min.y, 0f));
    }
    
    /// <summary>
    /// Boundsを取得
    /// </summary>
    private static Bounds GetBounds(this RectTransform self)
    {
        var min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
        var max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
        self.GetWorldCorners(s_Corners);
        for (var index2 = 0; index2 < 4; ++index2)
        {
            min = Vector3.Min(s_Corners[index2], min);
            max = Vector3.Max(s_Corners[index2], max);
        }
 
        max.z = 0f;
        min.z = 0f;
            
        Bounds bounds = new Bounds(min, Vector3.zero);
        bounds.Encapsulate(max);
        return bounds;
    }
}