之前写过一篇关于状态机的,上一篇讲过的我也就不再罗嗦了,不知道欢迎去查看我的上一篇随笔,主要是感觉上次自己封装的还是不行,所以又进行修改了一番!
我本人是个菜鸟,最开始接触状态机的时候,状态机一个可厉害的东西! 因为自己只是知道其大概流程并不是很清楚其内部代码应该怎么去实现!所以之前在学校的时候也是纠结了很长时间(本人比较笨),现在知道了其内部具体是怎么运作的!所以可以自己能够封装出来Simple的小例子,自己封装的可能会有一些BUG,大神路过望指正!
下面先讲状态机的原理,有限状态机主要是解决了游戏中状态的更换,以及省去了更换时的If else或者是Switch的繁杂语句,主要是通过有限状态机内部添加状态和记录状态可以转换的路径(方便装换使用),循环来实现摆脱If else或者是Switch的语句!
下面是详细的代码,里面都有很详细的注释
先看状态类
1 /// <summary> 2 /// 状态类 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public class MyState<T> 6 { 7 private T myState; 8 private T fatherState; 9 10 /// <summary> 11 /// 当前状态 12 /// </summary> 13 public T GetNowState 14 { 15 get 16 { 17 return myState; 18 } 19 } 20 21 22 /// <summary> 23 /// 返回父状态 24 /// </summary> 25 public T GetFatherState 26 { 27 get 28 { 29 return fatherState; 30 } 31 set 32 { 33 if (fatherState == null) 34 { 35 fatherState = value; 36 } 37 38 } 39 } 40 41 42 //自己的状态 父状态 43 public MyState(T nowestate,T fathertate) 44 { 45 myState = nowestate; 46 47 fatherState = fathertate; 48 49 } 50 51 52 /// <summary> 53 /// 转换状态之前触发的事件 54 /// </summary> 55 public event FsmEvent DoBeforeEntering; 56 public void DoEntery() 57 { 58 if (DoBeforeEntering != null) 59 { 60 DoBeforeEntering(); 61 } 62 else 63 { 64 Debug.Log(myState.ToString() + "没有添加事件"); 65 } 66 67 } 68 69 70 /// <summary> 71 /// 转换状态之后触发的事件 72 /// </summary> 73 public event FsmEvent DoBeforeLeaving; 74 public void DoLeave() 75 { 76 if (DoBeforeLeaving != null) 77 { 78 DoBeforeLeaving(); 79 } 80 else 81 { 82 Debug.Log(myState.ToString() + "没有绑定事件"); 83 } 84 85 } 86 87 88 /// <summary> 89 /// Act是表现当前状态行为的函数 90 /// </summary> 91 public event FsmEvent Act; 92 public void DoAction() 93 { 94 if (Act != null) 95 { 96 Act(); 97 } 98 else 99 { 100 Debug.Log(myState.ToString() + "没有绑定事件"); 101 } 102 } 103 }
然后是记录状态类的fsm类
1 public class MyFSM<T> 2 { 3 private Dictionary<T,List<MyState<T>>> TranslatList = new Dictionary<T,List<MyState<T>>>(); 4 5 private Dictionary<T, MyState<T>> AllState = new Dictionary<T,MyState<T>>(); 6 7 private T nowState; 8 9 public void OnStart(T _t) 10 { 11 nowState = _t; 12 } 13 14 /// <summary> 15 /// 添加装换状态列表 16 /// </summary> 17 /// <param name="t"></param> 18 /// <param name="_myStateList"></param> 19 public void AddTranslat(T t, List<MyState<T>> _myStateList) 20 { 21 if (TranslatList.ContainsKey(t)) 22 { 23 TranslatList[t] = _myStateList; 24 Debug.Log("重置转换状态"); 25 } 26 else 27 { 28 TranslatList.Add(t, _myStateList); 29 } 30 31 } 32 33 /// <summary> 34 /// 添加单独的装换状态 35 /// </summary> 36 /// <param name="t"></param> 37 /// <param name="_myState"></param> 38 public void AddTranslat(T t, MyState<T> _myState) 39 { 40 if (TranslatList.ContainsKey(t)) 41 { 42 List<MyState<T>> _myStateList = new List<MyState<T>>(); 43 _myStateList = TranslatList[t]; 44 if (_myStateList.Contains(_myState)) 45 { 46 return; 47 } 48 else 49 { 50 _myStateList.Add(_myState); 51 TranslatList[t] = _myStateList; 52 } 53 } 54 else 55 { 56 List<MyState<T>> _myStateList = new List<MyState<T>>(); 57 _myStateList.Add(_myState); 58 } 59 } 60 61 /// <summary> 62 /// 添加状态 63 /// </summary> 64 /// <param name="t"></param> 65 /// <param name="_state"></param> 66 public void AddState(T t, MyState<T> _state) 67 { 68 if (AllState.ContainsKey(t)) 69 { 70 AllState[t] = _state; 71 Debug.Log("重置状态"); 72 } 73 else 74 { 75 AllState.Add(t, _state); 76 } 77 } 78 79 /// <summary> 80 /// 执行 81 /// </summary> 82 public void Execution() 83 { 84 AllState[nowState].DoAction(); 85 } 86 87 88 /// <summary> 89 /// 状态转换 90 /// </summary> 91 /// <param name="_nextT"></param> 92 /// <returns></returns> 93 public bool StateTranslat(T _nextT) 94 { 95 //判读是否是同一个状态 96 //是否可以进入 97 //执行本状态最后命令 98 //切换状态 99 //执行本状态的开始命令 100 if (!nowState.Equals(_nextT)) 101 { 102 if (TranslatList[nowState].Contains(AllState[_nextT])) 103 //if (nowState.Equals(AllState[_nextT].GetFatherState)) 104 { 105 MyState<T> state = AllState[nowState]; 106 state.DoEntery(); 107 nowState = _nextT; 108 state = AllState[nowState]; 109 state.DoEntery(); 110 return true; 111 } 112 else 113 { 114 return false; 115 } 116 } 117 else 118 { 119 return false; 120 } 121 } 122 123 124 /// <summary> 125 /// 关闭FSM 126 /// </summary> 127 public void Close() 128 { 129 TranslatList.Clear(); 130 AllState.Clear(); 131 } 132 133 }
以上就是自己封装的fsm,有什么不对的地方欢迎大家指正!