zoukankan      html  css  js  c++  java
  • 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;
        }
        
    }
  • 相关阅读:
    Android 获取View在屏幕中的位置【转】
    算法学习资源 -- 2018年8月21日星期二
    Activity SingleInstance启动模式
    Android Studio添加aar依赖的两种方式
    Multiple dex files define Lcom/google/gson/internal/Streams$AppendableWriter$CurrentWrite;
    Android Studio添加aar依赖
    jdk-8u181-docs.chm -- 制作时间2018年8月12日
    大串中查找校串出现的次数(11)
    字符串反转(10)
    String类的替换方法(9)
  • 原文地址:https://www.cnblogs.com/DazeJiang/p/14386939.html
Copyright © 2011-2022 走看看