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; } }