什么是有限状态机:
有限状态机是一种用来进行对象行为建模的工具,作用是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。简单理解就是:状态满足条件下的一种处理机制。
有限状态机,任意时刻都处于有限状态集合中的某一状态。当获得一个输入字符时,将从当前状态转换到另一状态或仍保持当前状态。
每一个状态都有三种行为:进入、 执行、 离开。
对状态机有一个简单的了解之后,那么状态机在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 }
接下来,讲解下状态机在流程应用方面是如何使用的。