- 有限状态机的基类,包含各种状态
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum Transition { NullTransition=0, SeePlayer, LostPlayer } public enum StateID { NullStateID=0, Patrol, Chase } public abstract class FSMState { protected StateID stateID; public StateID ID { get { return stateID; } } protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>(); protected FSMSystem fsm; public FSMState(FSMSystem fsm) { this.fsm = fsm; } public void AddTransition(Transition transition,StateID id) { if (transition==Transition.NullTransition) { Debug.LogError("不允许NullTransition");return; } if (id==StateID.NullStateID) { Debug.LogError("不允许NullStateID");return; } if (map.ContainsKey(transition)) // 判断key是否存在 { Debug.LogError("添加转换条件的时候" + transition + "已经存在于map中");return; } map.Add(transition, id); } public void DeleteTransition(Transition transition) { if (transition == Transition.NullTransition) { Debug.LogError("不允许NullTransition"); return; } if (map.ContainsKey(transition)==false) // 判断key是否存在 { Debug.LogError("删除转换条件的时候" + transition + "不存在于map中"); return; } map.Remove(transition); } public StateID GetOutputState (Transition transition) { if (map.ContainsKey(transition)) { return map[transition]; } return StateID.NullStateID; } //进入状态之前的虚函数 public virtual void DoBeforEntering() { } //离开状态,状态发生转换 public virtual void DoAfterLeaving() { } //抽象方法必须重写 public abstract void Act(GameObject gameObject); //判断转换条件 public abstract void Reason(GameObject gameObject); }
- 控制状态之间的转换
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FSMSystem { private Dictionary<StateID, FSMState> states=new Dictionary<StateID, FSMState>(); private StateID currentStateID; private FSMState currentState; public void AddState(FSMState s) { if (s==null) { Debug.LogError("FSMState不能为空");return; } //默认状态 if (currentState==null) { currentState = s; currentStateID = s.ID; } //添加到字典里 if (states.ContainsKey(s.ID)) { Debug.LogError("状态" + s.ID + "已经存在");return; } states.Add(s.ID, s); } public void DeleteState(StateID id) { if (id==StateID.NullStateID) { Debug.LogError("无法删除空状态");return; } if (states.ContainsKey(id)==false) { Debug.LogError("无法删除不存在的:" + id);return; } states.Remove(id); } //根据条件进行状态切换 public void PerformTransition(Transition transition) { if (transition ==Transition.NullTransition) { Debug.LogError("无法执行空的转换条件");return; } StateID id = currentState.GetOutputState(transition); if (id==StateID.NullStateID) { Debug.LogWarning("当前状态" + currentStateID + "无法根据转换条件" + transition + "发生转换");return; } FSMState fSMState = states[id]; currentState.DoAfterLeaving(); //旧状态离开 currentState = fSMState; currentStateID = id; currentState.DoBeforEntering(); //新状态进入 } //调用Act方法 public void Update(GameObject gameObject) { currentState.Act(gameObject); currentState.Reason(gameObject); } }
- 敌人类
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Enemy : MonoBehaviour { private FSMSystem fsm; void Start () { InitFSM(); } //对有限状态机进行初始化 private void InitFSM() { fsm = new FSMSystem(); FSMState patrolState = new PatrolState(fsm); //转换条件 patrolState.AddTransition(Transition.SeePlayer,StateID.Chase); FSMState chaseState = new ChaseState(fsm); chaseState.AddTransition(Transition.LostPlayer, StateID.Patrol); fsm.AddState(patrolState); fsm.AddState(chaseState); } void Update () { fsm.Update(this.gameObject); } }
- 巡逻状态和追击状态
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PatrolState : FSMState { //路径点 private List<Transform> path = new List<Transform>(); private int index = 0; //移动的开始索引 private Transform playerTransform; public PatrolState(FSMSystem fsm) : base(fsm) { stateID = StateID.Patrol; //在这里获取一次,节省性能 Transform pathTran = GameObject.Find("Path").transform; Transform[] children = pathTran.GetComponentsInChildren<Transform>(); //还包含父物体 //剔除父物体 foreach (Transform child in children) { if (child!= pathTran) { path.Add(child); } } playerTransform = GameObject.Find("Player").transform; } //这个方法在FSMSystem中调用 public override void Act(GameObject gameObject) { gameObject.transform.LookAt(path[index].position); gameObject.transform.Translate(Vector3.forward * Time.deltaTime * 3); if (Vector3.Distance(gameObject.transform.position,path[index].position)<1) //自身位置与目标位置的距离 { index++; index %= path.Count; //index在数组内循环 } } public override void Reason(GameObject gameObject) { //与主角距离小于3的时候开始追击玩家 if (Vector3.Distance(playerTransform.position,gameObject.transform.position)<3) { fsm.PerformTransition(Transition.SeePlayer); } } }
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ChaseState : FSMState { private Transform playerTransform; public ChaseState(FSMSystem fsm) : base(fsm) { stateID = StateID.Chase; playerTransform = GameObject.Find("Player").transform; } public override void Act(GameObject gameObject) { gameObject.transform.LookAt(playerTransform.position); gameObject.transform.Translate(Vector3.forward * 2 * Time.deltaTime); } public override void Reason(GameObject gameObject) { //与主角距离大于6时,执行寻路状态 if (Vector3.Distance(playerTransform.position, gameObject.transform.position) > 6) { fsm.PerformTransition(Transition.LostPlayer); } } }
AI-有限状态机(追击,巡逻)
最新推荐文章于 2023-11-18 17:12:22 发布