什么是有限狀態機:
有限狀態機是一種用來進行對象行為建模的工具,作用是描述對象在它的生命周期內所經歷的狀態序列,以及如何響應來自外界的各種事件。簡單理解就是:狀態滿足條件下的一種處理機制。
有限狀態機,任意時刻都處於有限狀態集合中的某一狀態。當獲得一個輸入字符時,將從當前狀態轉換到另一狀態或仍保持當前狀態。
每一個狀態都有三種行為:進入、 執行、 離開。
對狀態機有一個簡單的了解之后,那么狀態機在unity游戲開發中有哪些應用呢?
大多游戲都有以下流程:
這些流程,我們是不是可以理解為狀態。
在AI 方面,游戲中的玩家行為大致有以下狀態:
站立(待機)、跑、跳、普攻、技能1,技能2,技能3,受傷、控制(眩暈、禁錮)、死亡 等等
以上2種舉例都可體現有限狀態機在游戲中的應用。故設計通用的狀態機就顯得很有必要。而不是為每一個應用都寫一個狀態機。
廢話不多說,直接上代碼
狀態機基類:都存在編號、當前狀態 抽象到基類。
1 public abstract class TestFsmBase 2 { 3 /// <summary>
4 /// 狀態機編號 5 /// </summary>
6 public int FsmId { get; private set; } 7
8 /// <summary>
9 /// 狀態機當前的狀態 10 /// </summary>
11 public sbyte CurrState; 12
13
14 public TestFsmBase(int fsmId) 15 { 16 FsmId = fsmId; 17 } 18
19 /// <summary>
20 /// 關閉 21 /// </summary>
22 public abstract void ShutDown(); 23 }
狀態機狀態:進入 執行 離開 最基本的三種行為。
1 public class TestFsmState<T> where T : class
2 { 3 public TestFsm<T> CurrFsm; 4
5 public virtual void OnEnter() 6 { 7 } 8
9 public virtual void OnUpdate() 10 { 11 } 12
13 public virtual void OnLeave() 14 { 15 } 16
17 public virtual void OnDestroy() 18 { 19
20 } 21 }
狀態機:
1.狀態機的擁有者
2.狀態機都有哪些狀態
3.切換狀態
4.關閉狀態機
1 using System.Collections.Generic; 2
3 public class TestFsm<T> : TestFsmBase where T : class
4 { 5 /// <summary>
6 /// 狀態機擁有者 7 /// </summary>
8 public T Owner { get; private set; } 9
10 public TestFsmState<T> m_CurrFsmState; 11
12 public Dictionary<sbyte, TestFsmState<T>> m_StateDic; 13
14
15 public TestFsm(int fsmId, T owner, TestFsmState<T>[] status) : base(fsmId) 16 { 17 Owner = owner; 18 m_StateDic = new Dictionary<sbyte, TestFsmState<T>>(); 19 for (int i = 0; i < status.Length; i++) 20 { 21 m_StateDic[(sbyte)i] = status[i]; 22 status[i].CurrFsm = this;//狀態的狀態機就是Fsm本身
23 } 24 CurrState = -1; 25 } 26
27 /// <summary>
28 /// 獲取狀態 29 /// </summary>
30 /// <returns></returns>
31 public TestFsmState<T> GetState(sbyte stateType) 32 { 33 m_StateDic.TryGetValue(stateType, out TestFsmState<T> fsmState); 34 return fsmState; 35 } 36
37 /// <summary>
38 /// 切換狀態 39 /// </summary>
40 /// <param name="newState"></param>
41 public void ChangeState(sbyte newState) 42 { 43 //上一個狀態離開 新狀態進入
44 if (newState == CurrStateType) return; 45 if (m_CurrFsmState != null) 46 { 47 m_CurrFsmState.OnLeave(); 48 } 49 if (m_StateDic.TryGetValue(newState, out TestFsmState<T> newFsmState)) 50 { 51 CurrState = newState; 52 m_CurrFsmState = newFsmState; 53 m_CurrFsmState.OnEnter(); 54 } 55 } 56
57 public void OnUpdate() 58 { 59 if (m_CurrFsmState != null) 60 { 61 m_CurrFsmState.OnUpdate(); 62 } 63 } 64
65 /// <summary>
66 /// 關閉狀態機 67 /// </summary>
68 public override void ShutDown() 69 { 70 if (m_CurrFsmState != null) 71 { 72 m_CurrFsmState.OnLeave(); 73 } 74 var enumerator = m_StateDic.GetEnumerator(); 75 while (enumerator.MoveNext()) 76 { 77 enumerator.Current.Value.OnDestroy(); 78 } 79 m_StateDic.Clear(); 80 } 81 }
狀態機管理器:.創建 、存在、 銷毀
1 using System; 2 using System.Collections.Generic; 3
4 /// <summary>
5 /// 狀態機管理器 6 /// </summary>
7 public class TestFsmManager : IDisposable 8 { 9 private int m_tempFsmId = 1; 10 private readonly Dictionary<int, TestFsmBase> fmsDic; 11
12 public TestFsmManager() 13 { 14 fmsDic = new Dictionary<int, TestFsmBase>(); 15 } 16
17 /// <summary>
18 /// 創建 19 /// </summary>
20 /// <typeparam name="T"></typeparam>
21 /// <param name="own"></param>
22 /// <param name="status"></param>
23 /// <returns></returns>
24 public TestFsm<T> CreateFsm<T>(T owner, TestFsmState<T>[] status) where T : class
25 { 26 TestFsm<T> fsm = new TestFsm<T>(m_tempFsmId++, owner, status); 27 fmsDic[m_tempFsmId] = fsm; 28 return fsm; 29 } 30
31 /// <summary>
32 /// 是否存在 33 /// </summary>
34 /// <param name="fsmId"></param>
35 /// <returns></returns>
36 public bool HasFsm(int fsmId) 37 { 38 return fmsDic.ContainsKey(fsmId); 39 } 40
41 /// <summary>
42 /// 銷毀 43 /// </summary>
44 /// <param name="fsmId"></param>
45 public void DestroyFsm(int fsmId) 46 { 47 if (fmsDic.TryGetValue(fsmId, out TestFsmBase fsmBase)) 48 { 49 fsmBase.ShutDown(); 50 fmsDic.Remove(fsmId); 51 } 52 } 53
54 public void Dispose() 55 { 56 var enumerator = fmsDic.GetEnumerator(); 57 while (enumerator.MoveNext()) 58 { 59 enumerator.Current.Value.ShutDown(); 60 } 61 fmsDic.Clear(); 62 } 63 }
接下來,講解下狀態機在流程應用方面是如何使用的。