unity 判断某一个点在不规则矩形内限制移动

2022 06 15

1判断 菱形两个相邻的点 和坐标原点 形成的三角区域

判断这个点 是否在这个扇形区域

  private bool TestCross(Vector3 a, Vector3 b)
        {
            //计算向量 a、b 的叉积,结果为 向量   
            Vector3 c = Vector3.Cross(a, b);

            // 通过反正弦函数获取向量 a、b 夹角(默认为弧度)  
            float radians = Mathf.Asin(Vector3.Distance(Vector3.zero, Vector3.Cross(a.normalized, b.normalized)));
            float angle = radians * Mathf.Rad2Deg;

            // 判断顺时针、逆时针方向,是在 2D 平面内的,所以需指定一个平面,  
            //下面以X、Z轴组成的平面为例 , (Y 轴为纵轴),  
            // 在 X、Z 轴平面上,判断 b 在 a 的顺时针或者逆时针方向,  
            if (c.y > 0)
            {
                return true;
                // b 在 a 的顺时针方向  
            }
            else if (c.y == 0)
            {
                return true;
                // b 和 a 方向相同(平行)  
            }
            else
            {
                return false;
                // b 在 a 的逆时针方向  
            }
        }

2 在计算这个点是否 封闭三角区域移动的最大对应的坐标 进行限制

private Vector3 RetDisTanceV3(Vector3 ve, Vector3 VeMin, Vector3 VeMax)
        {
            Vector3 veOut = Vector3.zero;

            ve.y = 0;
            VeMin.y = 0;
            VeMax.y = 0;
            Vector3 MinOrmax = new Vector3(VeMax.x - VeMin.x, 0, VeMax.z - VeMin.z);//向量 vemin--vemax
            Vector3 minOrZero = -VeMin;



            float DotMinMax = Vector3.Angle(MinOrmax, minOrZero);//最小位置 和原点 夹角



            Vector3 veOrVemin = new Vector3(ve.x - VeMin.x, 0, ve.z - VeMin.z);//min到ve的向量
            float currentAngle = Vector3.Angle(veOrVemin, MinOrmax);//算出 min到max向量 和min 到ve向量的夹角

            float maxOrAng = Vector3.Angle(minOrZero, veOrVemin);//算出 min到ve向量 和min 到原点向量的夹角
            float minOrVeDis = Mathf.Sqrt((VeMin.x - ve.x) * (VeMin.x - ve.x) + (VeMin.z - ve.z) * (VeMin.z - ve.z));//算出最小点到 当前位置的距离

            if (!Mathf.Approximately(maxOrAng, DotMinMax))
            {
                float minAndveDis = minOrVeDis * Mathf.Cos(currentAngle * Mathf.Deg2Rad);
                //在我的 范围内
                float r = Mathf.Sqrt((VeMin.x - VeMax.x) * (VeMin.x - VeMax.x) + (VeMin.z - VeMax.z) * (VeMin.z - VeMax.z));
                veOut.z = (minAndveDis * (VeMax.z - VeMin.z)) / r + VeMin.z;
                veOut.x = (minAndveDis * (VeMax.x - VeMin.x)) / r + VeMin.x;
            }
            else
            {
                //刚好在我的范围
                veOut = ve;
            }


            return veOut;
        }

3列如 我进行一个菱形测试(需要多边形 传入多个点信息)

 /// <summary>
        /// 限制的四个 最大边界  
        /// 要求 以 ABCD 的排序 顺时针添加 
        /// 可以以任意点 为起点的 (必须为顺时针 添加)
        /// </summary>
        Vector3 MaximizeBoundaryA = new Vector3(20, 0, 0);
        Vector3 MaximizeBoundaryB = new Vector3(0, 0, 20);
        Vector3 MaximizeBoundaryC = new Vector3(-20, 0, 0);
        Vector3 MaximizeBoundaryD = new Vector3(0, 0, -20);
        private Vector3 SetProPistion(Vector3 ve)
        {
            Vector3 veou = Vector3.zero;
            if (TestCross(ve, MaximizeBoundaryA) && !TestCross(ve, MaximizeBoundaryB))
            {

                veou = RetDisTanceV3(ve, MaximizeBoundaryA, MaximizeBoundaryB);
            }
            else if (TestCross(ve, MaximizeBoundaryD) && !TestCross(ve, MaximizeBoundaryA))
            {
                veou = RetDisTanceV3(ve, MaximizeBoundaryD, MaximizeBoundaryA);
            }
            else if (TestCross(ve, MaximizeBoundaryB) && !TestCross(ve, MaximizeBoundaryC))
            {
                veou = RetDisTanceV3(ve, MaximizeBoundaryB, MaximizeBoundaryC);
            }
            else //(TestCross(ve, MaximizeBoundaryC) && !TestCross(ve, MaximizeBoundaryD))
            {
                veou = RetDisTanceV3(ve, MaximizeBoundaryC, MaximizeBoundaryD);
            }

            return veou;
        }

2022 06 24
上面 代码 修改已知BUG 如果检查不规则多边形 会有问题


//把上面的的  private bool TestCross(Vector3 a, Vector3 b) 改为下面的这个方法
private bool TestCross(Vector3 start, Vector3 a,Vector3 b)
{
   var v1=a-start;
   var v2=b-start;
   return v1.x*v2.z-v2.x*v1.z<0
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_283886981

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值