zl程序教程

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

当前栏目

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

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

扇形范围判断,其实我们可以理解为一个圆形的判断变种,只是在特定的圆形角度里面才会判断,如果不在这个角度中,直接返回一个false即可.

首先还是先画出一个扇形,我们这样来设计,比如这个扇形的角度是60度,我们分为左右,一边30度,这样对于程序好写一点,首先画出扇形的两个边:

 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public class Fanshaped : MonoBehaviour
 6{
 7    public float angel = 60;
 8    public float radius = 4;
 9
10
11    private void OnDrawGizmos()
12    {
13        //
14        float x = radius * Mathf.Sin(angel / 2 * Mathf.Deg2Rad);//角度转换为弧度
15        float y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
16        Vector3 a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
17        Vector3 b = new Vector3(transform.position.x + x, 0, transform.position.z + y);
18
19        Gizmos.DrawLine(transform.position, a);
20        Gizmos.DrawLine(transform.position, b);
21
22
23
24    }
25}

然后就是和圆形差不多的算法,绘制一个弧形:

 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public class Fanshaped : MonoBehaviour
 6{
 7    public float angel = 60;
 8    public float radius = 4;
 9    public int count = 10;//扇形的精度
10
11    private void OnDrawGizmos()
12    {
13        //
14        float x = radius * Mathf.Sin(angel / 2 * Mathf.Deg2Rad);//角度转换为弧度
15        float y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
16        Vector3 a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
17        Vector3 b = new Vector3(transform.position.x + x, 0, transform.position.z + y);
18
19        Gizmos.DrawLine(transform.position, a);
20        Gizmos.DrawLine(transform.position, b);
21
22        float half = angel / 2;
23
24        for (int i = 0; i <= count ; i++)
25        {  
26
27            float temp = (half / count);
28            temp *= i; 
29            x = radius * Mathf.Sin((temp) * Mathf.Deg2Rad);
30            y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
31            a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
32            Gizmos.DrawSphere(a, 0.05f);
33            x = radius * Mathf.Sin((-temp) * Mathf.Deg2Rad);
34            y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
35            a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
36            Gizmos.DrawSphere(a, 0.05f);
37        }
38
39    }
40}

绘制的弧形如下:

下面我们开始判断点是否在扇形内:

 1using System.Collections;
 2using System.Collections.Generic;
 3using UnityEngine;
 4
 5public class Fanshaped : MonoBehaviour
 6{
 7    public Transform Point;
 8
 9    public float angel = 60;
10    public float radius = 4;
11    public int count = 10;//扇形的精度
12
13    private void OnDrawGizmos()
14    {
15        //
16        float x = radius * Mathf.Sin(angel / 2 * Mathf.Deg2Rad);//角度转换为弧度
17        float y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
18        Vector3 a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
19        Vector3 b = new Vector3(transform.position.x + x, 0, transform.position.z + y);
20
21        Gizmos.DrawLine(transform.position, a);
22        Gizmos.DrawLine(transform.position, b);
23
24        float half = angel / 2;
25
26        if (IsInRange(Point))
27        {
28            Gizmos.color = Color.red;
29        }
30        else
31        {
32            Gizmos.color = Color.blue;
33        }
34
35        for (int i = 0; i <= count ; i++)
36        {  
37
38            float temp = (half / count);
39            temp *= i; 
40            x = radius * Mathf.Sin((temp) * Mathf.Deg2Rad);
41            y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
42            a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
43            Gizmos.DrawSphere(a, 0.05f);
44            x = radius * Mathf.Sin((-temp) * Mathf.Deg2Rad);
45            y = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(x, 2f));
46            a = new Vector3(transform.position.x - x, 0, transform.position.z + y);
47            Gizmos.DrawSphere(a, 0.05f);
48        }
49
50    }
51
52
53    public bool IsInRange( Transform target)
54    {
55        //攻击者位置指向目标位置的向量
56        Vector3 direction = target.position - transform.position;
57        //点乘积结果
58        float dot = Vector3.Dot(direction.normalized, transform.forward);
59        //反余弦计算角度
60        float offsetAngle = Mathf.Acos(dot) * Mathf.Rad2Deg;
61        return offsetAngle < angel  * .5f && direction.magnitude < radius ;
62    }
63}

我们像之前一样的去测试一下.

如果点在扇形内:

如果不在:

引申

那么如果是扇形的环呢?其实,我们只需要判断点到圆心的距离,是否是在环内就可以了.