zl程序教程

您现在的位置是:首页 >  其他

当前栏目

游戏开发中的数学问题:技能伤害的区域检测(三角形)

2023-03-07 09:47:08 时间

三角形呢,其实是一个比较复杂的判断,绘制图像倒还好说,就是三个点,直接就可以绘制出来一个三角形,不过为了将问题简单化,所以还是老样子,我们的三角形三个点的Y轴都是0.

 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public class Triangle : MonoBehaviour
 6{
 7    public Transform pos1;
 8    public Transform pos2;
 9    public Transform pos3;
10
11    private void OnDrawGizmos()
12    {
13        Gizmos.DrawLine(pos1.position, pos2.position);
14        Gizmos.DrawLine(pos2.position, pos3.position);
15        Gizmos.DrawLine(pos3.position, pos1.position);
16    }
17}

太简单了,就不放图片了.反正各位都能看出来

好的,接下来就要说到比较复杂的东西了,其实讲出来也不算复杂,只是初中的知识.判断一个点是否在三角形内,大概有3种办法

第一种办法:内角和法

连接P点和三角形的三个顶点,得到三条线段PA,PB和PC,求出这三条线段与三角形各边的夹角,如果所有的夹角的内角和为180,那么就说明P点在三角形内,否则,就不在.但是这种办法如果是几何题,那么很好解,但是在我们的程序中,这个不好实现,因为需要加6个角,然后各种向量的计算.所以一般的,这种耗费性能的操作,直接舍弃掉.

第二种办法:同向法

那么同向法怎么理解呢?就是不管你是顺时针还是逆时针去遍历这些线段,会发现P点始终在这条线的一侧,如果是顺时针,那么线段就是AB ,BC ,CA ,会发现P点始终就是在你的右侧. 如果不符合这个规律,那么这个点就不在三角形内.

第三种方法重心法

三角形上的点都有这样的一个特性,假如B点,假设是A点移动了AB的一段距离,C点就是A移动了AC距离, 其中UV的取值范围为正,且U+V<1.

我们这里直接使用重心法

 1using UnityEngine;
 2
 3public class Triangle :MonoBehaviour
 4{
 5
 6    public Transform V1, V2, V3, Point;
 7
 8    private void OnDrawGizmos()
 9    {
10        bool isInangle = IsPointInTriangle(V1.position , V2.position , V3.position , Point.position ); 
11        if (isInangle)
12        {
13            Gizmos.color = Color.red;
14        }
15        else
16        {
17            Gizmos.color = Color.blue;
18        }
19        Gizmos.DrawLine(V1.position , V2.position );
20        Gizmos.DrawLine(V2.position , V3.position );
21        Gizmos.DrawLine(V3.position , V1.position );
22    }
23
24
25
26    bool IsPointInTriangle(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 targetPoint)
27    {
28        Vector3 v0 = p2 - p1;
29        Vector3 v1 = p3 - p1;
30        Vector3 v2 = targetPoint - p1;
31
32        float _00 = Vector3.Dot(v0, v0);
33        float _01 = Vector3.Dot(v0, v1);
34        float _02 = Vector3.Dot(v0, v2);
35        float _11 = Vector3.Dot(v1, v1);
36        float _12 = Vector3.Dot(v1, v2);
37
38        float inver = 1 / (_00 * _11 - _01 * _01);
39        float u = (_11 * _02 - _01 * _12) * inver;
40        if (u < 0 || u > 1)
41            return false;
42        float v = (_00 * _12 - _01 * _02) * inver;
43        if (v < 0 || v > 1)
44            return false;
45        return u + v < 1;
46    }
47}

 我们来试试效果:当点在三角形内:

当点不在三角形内: