一个好的AI会使游戏的可玩性大大增长,我这里只是简单的AI。dom
大体思路:ide
设置好后怪物的巡逻路径点,正常状况下,怪物处于巡逻状态,每到一个路径点会停下来张望,若是player接近怪物达到必定的距离,怪物的状态会变成追踪状态,当距离player必定距离状态会变成攻击状态,当怪物追踪到距离路径包围盒必定距离状态会转换成Back状态,回到当前路径点状态切换回巡逻状态动画
怪物受攻击状态过程当中涉及怪物受击打动画(小坑),怪物死亡动画(后续更新)this
攻击过程当中player全屏掉血(后续更新)spa
上代码(不完整,主要思路)
code
//AI状态 public enum AI_State { None, Patrol,//巡逻 ChasingPlayer,//跟随 AimingPlayer,// AttackingPlayer,//攻击 Attacked,//受到攻击 Back,//返回状态 Dead,//死亡 } //敌人种类 public enum Enemy_Type { Soldier, } //当前状态 public AI_State actualState = AI_State.Patrol; private float chasingSpeed = 2f;//跟随速度 private float nomalPatrolSpeed = 2.0f;//巡逻速度 //追踪距离 private float chasingDistance = 6; //攻击距离 private float attackDistance = 1.5f; //最大追踪距离 private float maxChasingDistance = 22; //路径 public FPS_WaypointsRoute waypointRoute;//路径点 private int currentWayPoint = 0;//当前路径索引 [HideInInspector] public Transform[] waypoints; private float timeToWait = 3.0f;//到达一个路径点停留时间 private UnityEngine.AI.NavMeshAgent agent;//导航组件 private Animator animator; private AnimatorStateInfo info; void Start () { player = GameObject.FindGameObjectWithTag("Player"); agent = GetComponent<UnityEngine.AI.NavMeshAgent>(); animator = GetComponent<Animator>(); if (player) playerTransform = player.transform; //设置路径 SetWaypoints(); //设置随机等待时间 SetTimeToWait(); //设置初始路径点 SetWaypoint(waypoints[0].position); if (waypoints.Length > 0) { finalGoal = waypoints[0].transform.position; } bountCenter = GetCenter(waypointRoute.transform);//全部路径点的包围盒 } void Update () { if (animator) { info = animator.GetCurrentAnimatorStateInfo(0); } //路径包围盒距离Ai最大的距离 if (Vector3.Distance(this.transform.position, bountCenter) > maxChasingDistance) { actualState = AI_State.Patrol; } if (actualState != AI_State.Attacked) { if (playerActualDistance > chasingDistance) { if (lastState == AI_State.AttackingPlayer || lastState == AI_State.ChasingPlayer || lastState == AI_State.Attacked) { actualState = AI_State.Back; } else { actualState = AI_State.Patrol; } } else if (playerActualDistance <= chasingDistance && playerActualDistance >= attackDistance) { if (!info.IsName("Attack")) { actualState = AI_State.ChasingPlayer; } else { animator.ResetTrigger("AttackT"); } if (animator) { animator.ResetTrigger("AttackT"); } } else if (playerActualDistance < attackDistance) { actualState = AI_State.AttackingPlayer; } } else { FPS_Kill.Instance.UnNomalStrike = false; if (animator) { animator.SetBool("Idle", false); } if (playerActualDistance < attackDistance) { actualState = AI_State.AttackingPlayer; if (animator) animator.ResetTrigger("AttackT"); } else { actualState = AI_State.Attacked; } } switch (actualState) { case AI_State.Patrol: if (waypoints.Length > 0) { if (agent.remainingDistance > 0.5f && !waiting) { agent.SetDestination(finalGoal); if (animator) { animator.SetBool("Idle",false); } } else if (!waiting && waitTimer < actualTimeToWait ) { waiting = true; } if (waiting) { if (animator) { animator.SetBool("Idle", true); } StopMovement(); if (waitTimer < actualTimeToWait) waitTimer += Time.deltaTime; else ChangeWaytpoint(); } } break; case AI_State.ChasingPlayer: if (animator) { animator.SetBool("Idle", false); } agent.SetDestination(player.transform.position); lastState = AI_State.ChasingPlayer; break; case AI_State.AttackingPlayer: StopMovement(); LookToTarget(player.transform.position); AttackPlayer(); lastState = AI_State.AttackingPlayer; break; case AI_State.Back: agent.SetDestination(waypoints[currentWayPoint].transform.position); bloodValue = Mathf.Lerp(bloodValue, 10, (Time.time-temp)*0.001f); FPS_BloodStrip.Insatnce.ChangeBloodStrip(bloodValue / 10.0f, 0.0f, 1); if (agent.remainingDistance < 0.5f) { actualState = AI_State.Patrol; lastState = AI_State.None; FPS_Kill.Instance.UnNomalStrike = false; //回去进入巡逻状态满血 GetComponent<FPS_Health>().health = 10; FPS_BloodStrip.Insatnce.ChangeBloodStrip(10 / 10.0f, 0.0f, 1); } break; case AI_State.Attacked: agent.SetDestination(player.transform.position); lastState = AI_State.Attacked; break; case AI_State.Dead: StopMovement(); break; } } public void SetWaypoints() { if (waypointRoute) { waypoints = new Transform[waypointRoute.waypoints.Length]; for (int i = 0; i < (waypoints.Length); i++) { waypoints[i] = waypointRoute.waypoints[i]; } } } /// <summary> /// 中止移动 /// </summary> void StopMovement() { if (agent != null) { agent.velocity = Vector3.zero; } } /// <summary> /// 巡逻等待时间 /// </summary> void SetTimeToWait() { actualTimeToWait = Random.Range(timeToWait * 0.75f, -timeToWait * 0.75f) + timeToWait; } /// <summary> /// 更改路径点 /// </summary> void ChangeWaytpoint() { waiting = false; currentWayPoint++; if (currentWayPoint >= waypoints.Length) { currentWayPoint = 0; } waitTimer = 0.0f; SetTimeToWait(); SetWaypoint(waypoints[currentWayPoint].transform.position); } /// <summary> /// 设置路径点 /// </summary> /// <param name="Pos"></param> void SetWaypoint(Vector3 Pos) { SetRandomPosVar(Pos); agent.SetDestination(finalGoal); } /// <summary> /// 设置目标路径点 /// </summary> /// <param name="goal"></param> void SetRandomPosVar(Vector3 goal) { finalGoal = goal + new Vector3(Random.Range(-1, 1), 0, Random.Range(-1, 1)); }