在設計一中,我們把IState類設計了一下,接下來,我們寫一下FiniteStateMachine這個類,這個類主要的作用就是對於外界調用,這個類是獨立封裝的,不繼承Mono。這個類的功能是提供一個棧,用於存放FSState,還有通過Update進行狀態的切換,以及對棧的管理,Pop和Push操作以及狀態的註冊。最重要的一點是聲明瞭三個委託函數代碼如下:
public delegate void EnterState(string stateName); public delegate void PushState(string stateName, string lastStateName); public delegate void PopState();
主要是用於狀態之間的切換。定義了Dictionary和Stack,前者用於State註冊,後者是狀態切換。代碼如下:
protected Dictionary<string, FSState> mStates; protected Stack<FSState> mStateStack;
對應的相關處理函數如下:
public void Register(string stateName, IState stateObject) { if (mStates.Count == 0) mEntryPoint = stateName; mStates.Add(stateName, new FSState(stateObject, this, stateName, Enter, Push, Pop)); }
用於狀態機的註冊,對Stack的操作是如下兩個函數,一個是Pop,一個是Push函數。代碼如下:
public void Push(string newState) { string lastName = null; if (mStateStack.Count > 1) { lastName = mStateStack.Peek().StateName; } Push(newState, lastName); } protected void Push(string stateName, string lastStateName) { mStateStack.Push(mStates[stateName]); mStateStack.Peek().StateObject.OnEnter(lastStateName); } public void Pop() { Pop(null); } protected string Pop(string newName) { FSState lastState = mStateStack.Peek(); string newState = null; if (newName == null && mStateStack.Count > 1) { int index = 0; foreach (FSState item in mStateStack) { if (index++ == mStateStack.Count - 2) { newState = item.StateName; } } } else { newState = newName; } string lastStateName = null; if (lastState != null) { lastStateName = lastState.StateName; lastState.StateObject.OnExit(newState); } mStateStack.Pop(); return lastStateName; }
下面增加了狀態觸發消息事件,代碼如下:
public void Trigger(string eventName) { CurrentState.Trigger(eventName); } public void Trigger(string eventName, object param1) { CurrentState.Trigger(eventName, param1); } public void Trigger(string eventName, object param1, object param2) { CurrentState.Trigger(eventName, param1, param2); } public void Trigger(string eventName, object param1, object param2, object param3) { CurrentState.Trigger(eventName, param1, param2, param3); }
最後把FiniteStateMachine核心的功能給大家介紹完了,下面奉上整個類的代碼:
using UnityEngine; using System.Collections; using System.Collections.Generic; public class FiniteStateMachine { public delegate void EnterState(string stateName); public delegate void PushState(string stateName, string lastStateName); public delegate void PopState(); protected Dictionary<string, FSState> mStates; protected string mEntryPoint; protected Stack<FSState> mStateStack; public FiniteStateMachine() { mStates = new Dictionary<string, FSState>(); mStateStack = new Stack<FSState>(); mEntryPoint = null; } public void Update() { if (CurrentState == null) { mStateStack.Push(mStates[mEntryPoint]); CurrentState.StateObject.OnEnter(null); } CurrentState.StateObject.OnUpdate(); } public void Register(string stateName, IState stateObject) { if (mStates.Count == 0) mEntryPoint = stateName; mStates.Add(stateName, new FSState(stateObject, this, stateName, Enter, Push, Pop)); } public FSState State(string stateName) { return mStates[stateName]; } public void EntryPoint(string startName) { mEntryPoint = startName; } public FSState CurrentState { get { if (mStateStack.Count == 0) return null; return mStateStack.Peek(); } } public void Enter(string stateName) { Push(stateName, Pop(stateName)); } public void Push(string newState) { string lastName = null; if (mStateStack.Count > 1) { lastName = mStateStack.Peek().StateName; } Push(newState, lastName); } protected void Push(string stateName, string lastStateName) { mStateStack.Push(mStates[stateName]); mStateStack.Peek().StateObject.OnEnter(lastStateName); } public void Pop() { Pop(null); } protected string Pop(string newName) { FSState lastState = mStateStack.Peek(); string newState = null; if (newName == null && mStateStack.Count > 1) { int index = 0; foreach (FSState item in mStateStack) { if (index++ == mStateStack.Count - 2) { newState = item.StateName; } } } else { newState = newName; } string lastStateName = null; if (lastState != null) { lastStateName = lastState.StateName; lastState.StateObject.OnExit(newState); } mStateStack.Pop(); return lastStateName; } public void Trigger(string eventName) { CurrentState.Trigger(eventName); } public void Trigger(string eventName, object param1) { CurrentState.Trigger(eventName, param1); } public void Trigger(string eventName, object param1, object param2) { CurrentState.Trigger(eventName, param1, param2); } public void Trigger(string eventName, object param1, object param2, object param3) { CurrentState.Trigger(eventName, param1, param2, param3); } }
上面整個FSMStateMachine類就封裝完了,要知後事如何?且看系列三的講解。