Unity不同形状区域的检测

一:圆形区域检测


需要判断一点:
——发起检测的物体位置与目标位置的距离是否小于圆形半径

using UnityEngine;

public class AreaDetection : MonoBehaviour
{
    public Transform targetTrans;//目标位置(敌人位置)

    public float attackDis;//圆形的半径

    void Update()
    {
        float dis = Vector3.Distance(transform.position, targetTrans.position);
        if (dis <= attackDis )
        {
            Debug.Log("进入攻击区域");
        }
        else
        {
            Debug.Log("离开攻击区域");
        }
    }
}

二:扇形区域检测


需要判断两点:
——发起检测的物体位置与目标位置的距离是否小于扇形半径
——发起检测的物体与目标的夹角是否小于扇形角度的二分之一

using UnityEngine;

public class AreaDetection : MonoBehaviour
{
    public float attackDis;//扇形的半径
    public float attackAngle;//扇形的角度

    public Transform targetTrans;//目标位置(敌人位置)

    private void Update()
    {
        float dis = Vector3.Distance(transform.position, targetTrans.position);
        float angle = Vector3.Angle(transform.forward, targetTrans.position - transform.position);

        if (dis <= attackDis && angle <= attackAngle / 2)
        {
            Debug.Log("进入攻击区域");
        }
        else
        {
            Debug.Log("离开攻击区域");
        }
    }
}

得到两个向量的夹角可以用另一种方法:

float _angle = Mathf.Acos(Vector3.Dot(transform.forward.normalized, (targetTrans.position - transform.position).normalized)) * Mathf.Rad2Deg;

三:矩形区域检测


需要判断三点:
——发起检测的物体与目标是否小于等于90度
——发起检测的物体位置到目标位置的向量在发起检测物体前方向向量上的投影是否小于矩形的长度
——发起检测的物体位置到目标位置的向量在发起检测物体右方向向量上的投影是否小于矩形的一半宽度

using UnityEngine;

public class AreaDetection : MonoBehaviour
{
    public float attackDis_forward;//矩形的长度
    public float attackDis_right;//矩形的宽度一半

    public Transform targetTrans;//目标位置(敌人位置)

    private void Update()
    {
        Vector3 v = targetTrans.position - transform.position;

        float projectionDis_forward = Vector3.Dot(transform.forward, v) / 1;
        float projectionDis_right = Vector3.Dot(transform.right, v) / 1;
        if ((projectionDis_forward > 0 && projectionDis_forward <= attackDis_forward)
            && (Mathf.Abs(projectionDis_right) < attackDis_right))
        {
            Debug.Log("进入攻击区域");
        }
        else
        {
            Debug.Log("离开攻击区域");
        }
    }
}

四:绘制可视的检测区域图形

将脚本挂载到发起检测的物体(与AreaDetection脚本挂载到同一物体身上)

using System.Collections.Generic;
using UnityEngine;

public class DrawShape : MonoBehaviour
{
    private AreaDetection _area;//区域检测的脚本

    public static GameObject go;
    public static MeshFilter mf;
    public static MeshRenderer mr;
    public static Shader shader;

    private void Awake()
    {
        _area = GetComponent<AreaDetection>();
    }

    void Update()
    {
        //DrawCircleArea(transform, transform.localPosition, _area.attackDis);
        //DrawSectorArea(transform, transform.localPosition, _area.attackAngle, _area.attackDis);
        //DrawRectangleArea(transform, transform.localPosition, _area.attackDis_forward, _area.attackDis_right);
    }

    /// <summary>
    /// 绘制圆形区域
    /// </summary>
    /// <param name="t">圆形参考物</param>
    /// <param name="center">圆形的中心</param>
    /// <param name="radius">圆形的半径</param>
    public static void DrawCircleArea(Transform t, Vector3 center, float radius)
    {
        int pointAmount = 100;//点的数目,值越大曲线越平滑   
        float eachAngle = 360f / pointAmount;
        Vector3 forward = t.forward;

        List<Vector3> vertices = new List<Vector3>();
        for (int i = 0; i < pointAmount; i++)
        {
            Vector3 pos = Quaternion.Euler(0f, eachAngle * i, 0f) * forward * radius + center;
            vertices.Add(pos);
        }
        CreateMesh(vertices);
    }

    /// <summary>
    /// 绘制扇形区域
    /// </summary>
    /// <param name="t">扇形参考物</param>
    /// <param name="center">扇形的中心</param>
    /// <param name="angle">扇形的角度</param>
    /// <param name="radius">扇形的半径</param>
    public static void DrawSectorArea(Transform t, Vector3 center, float angle, float radius)
    {
        int pointAmount = 100;//点的数目,值越大曲线越平滑   
        float eachAngle = angle / pointAmount;
        Vector3 forward = t.forward;

        List<Vector3> vertices = new List<Vector3>();
        vertices.Add(center);
        for (int i = 1; i < pointAmount - 1; i++)
        {
            Vector3 pos = Quaternion.Euler(0f, -angle / 2 + eachAngle * (i - 1), 0f) * forward * radius + center;
            vertices.Add(pos);
        }
        CreateMesh(vertices);
    }

    /// <summary>
    /// 绘制矩形区域
    /// </summary>
    /// <param name="t">矩形参考物</param>
    /// <param name="bottomMiddle">矩形的中心点</param>
    /// <param name="length">矩形的长度</param>
    /// <param name="width">矩形的宽度一半</param>
    public static void DrawRectangleArea(Transform t, Vector3 bottomMiddle, float length, float width)
    {
        List<Vector3> vertices = new List<Vector3>();
        vertices.Add(bottomMiddle - t.right * width);
        vertices.Add(bottomMiddle - t.right * width + t.forward * length);
        vertices.Add(bottomMiddle + t.right * width + t.forward * length);
        vertices.Add(bottomMiddle + t.right * width);

        CreateMesh(vertices);
    }

    /// <summary>
    /// 创建Mesh
    /// </summary>
    /// <param name="vertices">存储顶点的列表</param>
    /// <returns></returns>
    private static GameObject CreateMesh(List<Vector3> vertices)
    {
        int[] triangles;
        Mesh mesh = new Mesh();
        int triangleAmount = vertices.Count - 2;
        triangles = new int[3 * triangleAmount];

        //根据三角形的个数,来计算绘制三角形的顶点顺序(索引)   
        //顺序必须为顺时针或者逆时针      
        for (int i = 0; i < triangleAmount; i++)
        {
            triangles[3 * i] = 0;//固定第一个点      
            triangles[3 * i + 1] = i + 1;
            triangles[3 * i + 2] = i + 2;
        }

        if (go == null)
        {
            go = new GameObject("DetectionArea");
            go.transform.position = new Vector3(0, 0.1f, 0);//让绘制的图形上升一点,防止被地面遮挡  
            mf = go.AddComponent<MeshFilter>();
            mr = go.AddComponent<MeshRenderer>();
            shader = Shader.Find("Unlit/Color");
        }
        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles;
        mf.mesh = mesh;
        mr.material.shader = shader;
        mr.material.color = Color.red;
        return go;
    }

}

猜你喜欢

转载自blog.csdn.net/LLLLL__/article/details/105801592