AI系统(二)

AI控制,AI物体挂载,负责通过视觉/听觉侦查的敌人,记录寻路点。

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class AIController : MonoBehaviour
{
    public float raudir_Sound = 10;  //听觉
    public float fov_Distance = 30; //视觉距离
    public float fov_Angle = 160; //视觉角度
    public List<Camp> enemyCamps = new List<Camp>(); //敌人的阵营

    public List<GameObject> targetsEmeny = new List<GameObject>();

    public int maxDetectDistance = 100;
    //视觉范围内敌人
    public List<GameObject> fov_Enemy = new List<GameObject>();
    //听觉范围敌人
    public List<GameObject> sounded_Enemy = new List<GameObject>();
    //看不到的敌人
    public List<GameObject> back_Enemy = new List<GameObject>();
    public List<Transform> wayPoint = new List<Transform>();
    private Transform nextWayIndex;
    //获取当前寻路点
    public Vector3 GetCurrPoint
    {
        get {
            if (nextWayIndex!=null)
            {
                return nextWayIndex.position;
            }
            return transform.position;
        }
    }
    //获取最近的寻路点
    public Vector3 GetNearestPoint
    {
        get
        {
            if (!FindNearestWayPoint())
            {
                return transform.position;
            }
            return nextWayIndex.position;
        }
    }
    //获取随机寻路点
    public Vector3 GetRandomPoint
    {
        get
        {
            if (nextWayIndex!=null)
            {
                return wayPoint[Random.Range(0, wayPoint.Count)].position ;
            }
            return transform.position;
        }
    }
    //获取下一个寻路点
    public Vector3 GetNextPoint
    {
        get
        {
            if (wayPoint!=null)
            {
                return wayPoint[(currWayPointIndex++) % wayPoint.Count].position;
            }
            return transform.position;
        }
    }
    private bool isFov;
    private int currWayPointIndex;
    private void Start()
    {
        UpdateCurrentEnemy();
    }
    /// <summary>
    /// 实时更新targetEnemy
    /// </summary>
    
    private void Update()
    {
        ClearCurrEnemy();
        for (int i = 0; i < targetsEmeny.Count; i++)
        {
            float cosValue = Vector3.Dot(transform.forward,Vector3.ProjectOnPlane((targetsEmeny[i].transform.position - transform.position),Vector3.up).normalized);
            if (cosValue>((180-fov_Angle)/180)) //-90---90  在前方 
            {
                fov_Enemy.Add(targetsEmeny[i]);
                isFov = true;
            }
            if ((targetsEmeny[i].transform.position-transform.position).magnitude<10)
            {
                sounded_Enemy.Add(targetsEmeny[i]);
                if (!isFov)
                {
                    back_Enemy.Add(targetsEmeny[i]);
                }
            }
            isFov = false;
        }

    }

    void ClearCurrEnemy()
    {
        sounded_Enemy.Clear();
        fov_Enemy.Clear();
        back_Enemy.Clear();
    }

    /// <summary>
    /// 绘制视野 yellow//听觉 red
    /// </summary>
    private void OnDrawGizmos()
    {
        // Handles.BeginGUI();
        Color oldColor1 = Handles.color;
        Color c1= Color.red;
        c1.a = 0.1f;
        Handles.color =c1;
        Handles.DrawSolidArc(transform.position, transform.up, transform.forward, 360, raudir_Sound);
        Handles.color = oldColor1;
        Color oldColor = Handles.color;
        Color c= Color.yellow;
        c.a = 0.1f;
        Handles.color = c;
        var beginDirection = Quaternion.AngleAxis(-fov_Angle*0.5f, Vector3.up) * transform.forward;
        Handles.DrawSolidArc(transform.position, transform.up, beginDirection, fov_Angle, fov_Distance);
        //Handles.EndGUI();
        Handles.color = oldColor;
    }
    void UpdateCurrentEnemy()
    {
        if (enemyCamps.Count<=0)
        {
            return;
        }
        for (int i = 0; i < enemyCamps.Count; i++)
        {
            List<GameObject> gameObjects = AIManager.Instance.GetTargetCamp(enemyCamps[i]);
            if (gameObjects == null)
                return;
            for (int j = 0; j < gameObjects.Count; j++)
            {
                if ((gameObjects[j].transform.position-transform.position).magnitude<maxDetectDistance)
                {
                    if (!ContainEnemy(gameObjects[j]))
                    {
                        targetsEmeny.Add(gameObjects[j]);
                    }
                    
                }
            }
        }
    }

    private bool ContainEnemy(GameObject obj)
    {
        for (int i = 0; i < targetsEmeny.Count; i++)
        {
            if (targetsEmeny[i].Equals(obj))
            {
                return true;
            }
        }
        return false;
    }
    /// <summary>
    /// 获取最近的敌人
    /// </summary>
    /// <param name="isInFov">是否在视野内</param>
    /// <returns></returns>
    public GameObject GetNearestEnemy(bool isInFov=false)
    {
        if (isInFov)
        {
            if (fov_Enemy.Count==0)
            {
                return null;
            }
            float dis = (fov_Enemy[0].transform.position - transform.position).magnitude;
            GameObject target = fov_Enemy[0];
            for (int i = 1; i < fov_Enemy.Count; i++)
            {
                float currdis = (fov_Enemy[i].transform.position - transform.position).magnitude;
                if (dis> currdis)
                {
                    dis = currdis;
                    target = fov_Enemy[i];
                }
            }
            return target;
        }
        else
        {
            if (sounded_Enemy.Count==0)
            {
                return null;
            }
            float dis = (sounded_Enemy[0].transform.position - transform.position).magnitude;
            GameObject target = sounded_Enemy[0];
            for (int i = 1; i < sounded_Enemy.Count; i++)
            {
                float currdis = (sounded_Enemy[i].transform.position - transform.position).magnitude;
                if (dis > currdis)
                {
                    dis = currdis;
                    target = sounded_Enemy[i];
                }
            }
            return target;
        }
    }
    /// <summary>
    /// 获取最远的敌人
    /// </summary>
    /// <returns></returns>
    public GameObject GetFurthestEnemy(bool isInFov = false)
    {
        if (isInFov)
        {
            if (fov_Enemy.Count == 0)
            {
                return null;
            }
            float dis = (fov_Enemy[0].transform.position - transform.position).magnitude;
            GameObject target = fov_Enemy[0];
            for (int i = 1; i < fov_Enemy.Count; i++)
            {
                float currdis = (fov_Enemy[i].transform.position - transform.position).magnitude;
                if (currdis>dis)
                {
                    dis = currdis;
                    target = fov_Enemy[i];
                }
            }
            return target;
        }
        else
        {
            if (sounded_Enemy.Count == 0)
            {
                return null;
            }
            float dis = (sounded_Enemy[0].transform.position - transform.position).magnitude;
            GameObject target = sounded_Enemy[0];
            for (int i = 1; i < sounded_Enemy.Count; i++)
            {
                float currdis = (sounded_Enemy[i].transform.position - transform.position).magnitude;
                if (currdis > dis)
                {
                    dis = currdis;
                    target = sounded_Enemy[i];
                }
            }
            return target;
        }

    }
    /// <summary>
    /// 前方距离范围内面向敌人的世界方向
    /// </summary>
    /// <returns></returns>
    public Vector3 GetEnemyBestDir(float distance)
    {

        if (fov_Enemy.Count==0)
        {
            return transform.forward;
        }
        Vector3 dir = Vector3.zero;
        for (int i = 0; i < fov_Enemy.Count; i++)
        {
            Vector3 currdis = fov_Enemy[i].transform.position - transform.position;
            float dis = currdis.magnitude;
            if (dis < distance)
            {
                dir += currdis* 1/ dis;   //距离越近主导方向的权重越大
            }
        }
        dir.Normalize();
        return dir;
    }

    /// <summary>
    /// 找到最近的寻路点
    /// </summary>
    /// <returns></returns>
    bool FindNearestWayPoint()
    {
        if (wayPoint.Count == 0)
        {
            return false;
        }

        float dis =float.MaxValue;
        for (int i = 0; i < wayPoint.Count; i++)
        {
            Vector3 dirVec = wayPoint[0].position - transform.position;
            float distance = dirVec.magnitude;
            if (dis> distance)
            {
                nextWayIndex = wayPoint[0];
                dis = distance;
                currWayPointIndex = i;
            }
        }
       
        return true;
    }
    
}

 

posted @ 2021-02-07 22:23  wsfw  阅读(75)  评论(0编辑  收藏  举报