Unity3d架构系列之- FSM有限状态机设计二

 

继续上篇文章在设计一中,我们实现了有限状态机管理类,接下来,我们实现FSState这个类,这里类主要是状态的基本操作以及事件触发。在这里我们定义了在FiniteStateMachine类里声明的三个委托。在FSState里面使用的代码如下:


protected FiniteStateMachine.EnterState mEnterDelegate;
protected FiniteStateMachine.PushState mPushDelegate;
protected FiniteStateMachine.PopState mPopDelegate;

这个FSState是独立的一个类,不继承Mono,我们定义了一个构造函数,将我们的委托进行了初始化:


public FSState(IState obj, FiniteStateMachine owner, string name, FiniteStateMachine.EnterState e, FiniteStateMachine.PushState pu, FiniteStateMachine.PopState po) {
mStateObject = obj;
mStateName = name;
mOwner = owner;
mEnterDelegate = e;
mPushDelegate = pu;
mPopDelegate = po;
mTranslationEvents = new Dictionary<string, FSEvent>();

}

我们声明了FSEvent事件处理函数用于将事件的名字和事件加入的Dictionary里面


public FSEvent On(string eventName) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
mTranslationEvents.Add(eventName, newEvent);
return newEvent;

}

加入到列表后,我们需要从表里面取出去执行,这就需要Trigger触发函数:


public void Trigger(string name) {
mTranslationEvents[name].Execute(null, null, null);
}

public void Trigger(string eventName, object param1) {
mTranslationEvents[eventName].Execute(param1, null, null);
}

public void Trigger(string eventName, object param1, object param2) {
mTranslationEvents[eventName].Execute(param1, param2, null);
}

public void Trigger(string eventName, object param1, object param2, object param3) {
mTranslationEvents[eventName].Execute(param1, param2, param3);

}

以上也是FSState类的核心代码,闲话少说,FSState类的整个代码,如下:


using System;
using System.Collections;
using System.Collections.Generic;

public class FSState {
protected FiniteStateMachine.EnterState mEnterDelegate;
protected FiniteStateMachine.PushState mPushDelegate;
protected FiniteStateMachine.PopState mPopDelegate;

protected IState mStateObject;
protected string mStateName;
protected FiniteStateMachine mOwner;
protected Dictionary<string, FSEvent> mTranslationEvents;

public FSState(IState obj, FiniteStateMachine owner, string name, FiniteStateMachine.EnterState e, FiniteStateMachine.PushState pu, FiniteStateMachine.PopState po) {
mStateObject = obj;
mStateName = name;
mOwner = owner;
mEnterDelegate = e;
mPushDelegate = pu;
mPopDelegate = po;
mTranslationEvents = new Dictionary<string, FSEvent>();
}

public IState StateObject {
get {
return mStateObject;
}
}

public string StateName {
get {
return mStateName;
}
}

public FSEvent On(string eventName) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
mTranslationEvents.Add(eventName, newEvent);
return newEvent;
}

public void Trigger(string name) {
mTranslationEvents[name].Execute(null, null, null);
}

public void Trigger(string eventName, object param1) {
mTranslationEvents[eventName].Execute(param1, null, null);
}

public void Trigger(string eventName, object param1, object param2) {
mTranslationEvents[eventName].Execute(param1, param2, null);
}

public void Trigger(string eventName, object param1, object param2, object param3) {
mTranslationEvents[eventName].Execute(param1, param2, param3);
}

public FSState On<T>(string eventName, Func<T, bool> action) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
newEvent.mAction = delegate (object o1, object o2, object o3) {
T param1;
try { param1 = (T)o1; } catch { param1 = default(T); }
action(param1);
return true;
};
mTranslationEvents.Add(eventName, newEvent);
return this;
}

public FSState On<T>(string eventName, Action<T> action) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
newEvent.mAction = delegate (object o1, object o2, object o3) {
T param1;
try { param1 = (T)o1; } catch { param1 = default(T); }
action(param1);
return true;
};
mTranslationEvents.Add(eventName, newEvent);
return this;
}

public FSState On<T1, T2>(string eventName, Func<T1, T2, bool> action) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
newEvent.mAction = delegate (object o1, object o2, object o3) {
T1 param1;
T2 param2;
try { param1 = (T1)o1; } catch { param1 = default(T1); }
try { param2 = (T2)o2; } catch { param2 = default(T2); }
action(param1, param2);
return true;
};
mTranslationEvents.Add(eventName, newEvent);
return this;
}

public FSState On<T1, T2>(string eventName, Action<T1, T2> action) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
newEvent.mAction = delegate (object o1, object o2, object o3) {
T1 param1;
T2 param2;
try { param1 = (T1)o1; } catch { param1 = default(T1); }
try { param2 = (T2)o2; } catch { param2 = default(T2); }
action(param1, param2);
return true;
};
mTranslationEvents.Add(eventName, newEvent);
return this;
}

public FSState On<T1, T2, T3>(string eventName, Func<T1, T2, T3, bool> action) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
newEvent.mAction = delegate (object o1, object o2, object o3) {
T1 param1;
T2 param2;
T3 param3;
try { param1 = (T1)o1; } catch { param1 = default(T1); }
try { param2 = (T2)o2; } catch { param2 = default(T2); }
try { param3 = (T3)o3; } catch { param3 = default(T3); }
action(param1, param2, param3);
return true;
};
mTranslationEvents.Add(eventName, newEvent);
return this;
}

public FSState On<T1, T2, T3>(string eventName, Action<T1, T2, T3> action) {
FSEvent newEvent = new FSEvent(eventName, null, this, mOwner, mEnterDelegate, mPushDelegate, mPopDelegate);
newEvent.mAction = delegate (object o1, object o2, object o3) {
T1 param1;
T2 param2;
T3 param3;
try { param1 = (T1)o1; } catch { param1 = default(T1); }
try { param2 = (T2)o2; } catch { param2 = default(T2); }
try { param3 = (T3)o3; } catch { param3 = default(T3); }
action(param1, param2, param3);
return true;
};
mTranslationEvents.Add(eventName, newEvent);
return this;
}
}

我们实现了FSState这个类,我们继续实现FSEvent事件处理类。在FSEvent类里面我们声明了FiniteStateMachine里面定义的委托函数。代码如下:


protected FiniteStateMachine.EnterState mEnterDelegate;
protected FiniteStateMachine.PushState mPushDelegate;
protected FiniteStateMachine.PopState mPopDelegate;

同时我们定义了一个枚举用于处理有限状态机的状态,使用了System里面自带的封装的一个具有三个参数并返回TResult参数制定的雷兴志的方法。


public Func<object,object,object,bool>   mAction = null;

这个FSEvent事件类也是独立的,不继承Mono。它的核心功能主要是处理FSState的Enter,Push,Pop。代码如下:


public FSState Enter(string stateName) {
mTargetState = stateName;
eType = EventType.ENTER;
return mStateOwner;
}

public FSState Push(string stateName) {
mTargetState = stateName;
eType = EventType.PUSH;
return mStateOwner;
}

public void Pop() {
eType = EventType.POP;
}

public void Execute(object o1,object o2,object o3) {
if (eType == EventType.POP) {
mPopDelegate();
}
else if (eType == EventType.PUSH) {
mPushDelegate(mTargetState, mOwner.CurrentState.StateName);
}
else if (eType == EventType.ENTER) {
mEnterDelegate(mTargetState);
}
else if (mAction != null) {
mAction(o1, o2, o3);
}
}

总的来说,FSEvent是通过调用Enter,Push,Pop,Execute执行状态的切换。下面把整个代码给大家展现一下:


using System;

public class FSEvent {
protected FiniteStateMachine.EnterState mEnterDelegate;
protected FiniteStateMachine.PushState mPushDelegate;
protected FiniteStateMachine.PopState mPopDelegate;

protected enum EventType { NONE, ENTER, PUSH, POP };
protected string mEventName;
protected FSState mStateOwner;
protected string mTargetState;
protected FiniteStateMachine mOwner;
protected EventType eType;
public Func<object,object,object,bool>   mAction = null;

public FSEvent(string name, string target, FSState state, FiniteStateMachine owner, FiniteStateMachine.EnterState e, FiniteStateMachine.PushState pu, FiniteStateMachine.PopState po) {
mStateOwner = state;
mEventName = name;
mTargetState = target;
mOwner = owner;
eType = EventType.NONE;
mEnterDelegate = e;
mPushDelegate = pu;
mPopDelegate = po;
}

public FSState Enter(string stateName) {
mTargetState = stateName;
eType = EventType.ENTER;
return mStateOwner;
}

public FSState Push(string stateName) {
mTargetState = stateName;
eType = EventType.PUSH;
return mStateOwner;
}

public void Pop() {
eType = EventType.POP;
}

public void Execute(object o1,object o2,object o3) {
if (eType == EventType.POP) {
mPopDelegate();
}
else if (eType == EventType.PUSH) {
mPushDelegate(mTargetState, mOwner.CurrentState.StateName);
}
else if (eType == EventType.ENTER) {
mEnterDelegate(mTargetState);
}
else if (mAction != null) {
mAction(o1, o2, o3);
}
}
}

设计二把FSM常用的类已经封装好了,接下来我们会在设计三中去封装一个EventSystem类。用于处理事件的注册,分发等功能。

作者:大洋    博客:http://jxwgame.blog.51cto.com