UGUI实现不规则形状图片触发

效果如下

UGUI实现不规则形状图片触发_第1张图片

有两种比较主流的实现方式,一种是根据图片像素的alpha值来判断是否触发响应,还有一种是自己框选一个多边体,判断点击位置是否在多变体内。
第一种像素使用限制颇多,但是也有一定的使用场景,https://www.cnblogs.com/msxh/p/9283266.html,这里马三详细说了使用方法和限制
我在这里实现的是第二种计算的方式

UGUI实现不规则形状图片触发_第2张图片

P点是鼠标位置,ABCD是多边形的点,如果图上对每个点计算叉乘的方向都是一致,那我们可以得出P点在多边形内部,有一定的叉乘知识应该可以推出来。叉乘可以看看这篇文章 https://blog.csdn.net/qq_33413868/article/details/87929981

下面上代码实现:

public class MImage : Image
{
    //多边形使用PolygonCollider2D来代替,但是推荐自己写一个,我们只需要使用collider2D.points来按顺序获取所有
    //的点,PolygonCollider2D似乎有些大材小用,这里只做演示
    private PolygonCollider2D collider2D;
    private bool? dir;
    protected override void Awake()
    {
        base.Awake();
        collider2D = GetComponent();
    }

    /// 
    /// unity判断是否选中的方法,可以继承Image来重写
    /// 
    /// 
    /// 
    /// 
    public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
    {
        dir = null;
        screenPoint = screenPoint - (Vector2)rectTransform.position;
        int len = collider2D.points.Length;
        for (int i = 0; i < len; i++)
        {
            //求每条边的方向向量
            var side_dir = collider2D.points[(i + 1) % len] - collider2D.points[i];
            //求当前点和边的向量叉乘 的朝向
            bool _dir = Vector3.Cross(screenPoint - collider2D.points[i], side_dir).z > 0;
            if (!dir.HasValue)
                dir = _dir;
            if (dir.Value != _dir)
                return false;
        }
        return true;
    }
}

还有第二种计算是使用collider自带的api

public bool IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera)
        {
            var worldPoint = Vector3.zero;
            var isInside = RectTransformUtility.ScreenPointToWorldPointInRectangle(
                _rectTransform,
                screenPos,
                eventCamera,
                out worldPoint
            );

            if (isInside)
            {
                isInside = _collider.OverlapPoint(worldPoint);
            }

            return isInside;
        }

 

你可能感兴趣的:(Unity3D,unity,ugui)