2.图形精确点击

本文介绍了一种基于射线与图形边框交点数目的点击检测算法,通过判断点击点是否位于图形内部,适用于未铺满整个rect的图形及镂空图形。文章详细解释了算法原理,并提供了Unity代码实现。

当图形未铺满 整个rect时,实现精确点击

一. 原理

通过点击点向右或向左的射线与图形边框的交点数来判断是否处于图形内,奇数表示处于图形内,偶数表示图形外。
在这里插入图片描述
对于镂空图形同样适用
在这里插入图片描述

二. 代码实现

重载写IsRaycastLocationValid返回点击位置是否有效

List<Vector3> vertexList = new List<Vector3>();

vertexList 中存放的是图形边框顶点位置
在这里插入图片描述

 public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
    {
        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,screenPoint,eventCamera,out localPoint);
        return IsValid(localPoint,vertexList);
    }

	//根据交点奇偶数判断
    private bool IsValid(Vector2 localPoint, List<Vector3> vertexList)
    {
        Debug.Log("click ="+ (GetCrossPointNum(localPoint, vertexList) % 2 == 1));
        return GetCrossPointNum(localPoint, vertexList) % 2 == 1;
    }

    //获取与边的交点数目
    private int GetCrossPointNum(Vector2 localPoint, List<Vector3> vertexList)
    {
        Vector3 vert1 = Vector3.zero;
        Vector3 vert2 = Vector3.zero;
        int vertexCount = vertexList.Count;
        int crossCount = 0;
        for (int i = 0; i < vertexCount-1; i++)
        {
            Debug.Log("i=" + i);
            vert1 = vertexList[i];
            vert2 = vertexList[i+1];
            if (IsYInRange(localPoint, vert1, vert2) && IsXInRange(localPoint, vert1, vert2))
            {
                crossCount++;
            }

        }
        return crossCount;
    }


    //判断点的y值是否在边的两点的y值之间,在则有交点,反之则没有
    private bool IsYInRange(Vector2 localPoint, Vector3 vert1,Vector3 vert2)
    {
        float max = Mathf.Max(vert1.y, vert2.y);
        float min = Mathf.Min(vert1.y, vert2.y);
        return min <= localPoint.y && localPoint.y <= max;
    }

	//获取交点的x坐标,取在点击点右面(或左面)的边
    private bool IsXInRange(Vector2 localPoint, Vector3 vert1, Vector3 vert2)
    {
        float k = (vert2.y - vert1.y) / (vert2.x - vert1.x);
        float crossX = vert2.x - (vert2.y - localPoint.y) / k;
        return crossX >= localPoint.x;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值