本系列笔记转载自游戏蛮牛专栏作家Jackel的论坛文章,详细介绍了FSM的创建与使用,特与众分享。链接:http://www.manew.com/thread-37136-1-1.html
该类是对外开放的,主要用于外界的调用,独立封装,不继承Mono。该类定义一个栈,用于存放FSState,通过Update进行状态的切换。对栈的管理及Pop和Push操作、状态机的注册。该类声明了三个重要的委托。代码如下:
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 FSState CurrentState
{
get
{
if( mStateStack.Count == 0 )
{
return null;
}
return mStateStack.Peek();
}
}
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 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 );
}
public 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 );
}
}
一、委托
这三个委托主要用于状态的转换。
1、EnterState
2、PushState
3、PopState
二、数据存取
1、protected Dictionary<string, FSState> mStates
2、protected Stack<FSState> mStateStack
栈用于状态机的注册,对Stack的操作主要是Pop和Push函数。
三、事件触发
事件的触发,主要是对Trigger进行了重载,实现不同状态事件的触发。