- 有限狀態機的基類,包含各種狀態
-
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-有限狀態機(追擊,巡邏)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.