有限状态机英文全称Finite State Machine,它的应用及其广泛,虽然主要是在Unity中的应用,但是核心内容无论你是用C#,java,Object—C都是一样的,这也是我这笔记的目的。
目录
1. 意图:
对对象状态间的行为和转化进行管理,方便扩展,维护。
2. 定义:
表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
3. 如何使用:
创建的数学模型状态机可分为四要素:
现态(State)条件(Transition)动作(Action)次态(State)
1.现态:是指当前所处的状态。
2.条件:又称为事件。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
3.动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必须的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
4.次态:条件满足后要迁往的新状态。‘次态’是相对于‘现态’而言的,‘次态’一旦被激活,就转变成新的‘现态’了。
要注意的两个问题:
1.避免把某个‘程序动作’当作是一种状态来处理,那么如何区分动作和状态?动作一旦执行完毕就结束了,而状态是相对稳定的,如果没有外部条件的触发,一个状态会一直持续下去。
2.状态划分时会漏掉一些状态,导致跳转逻辑不完整。所以维护一张状态表就非常必要了。从表中可以直观看出哪些状态直接存在
跳转路径,哪些状态直接不存在。如果不存在,就把相应的单元格置灰。每次写代码之前先把表格填写好,看着是否有‘漏太’,然后才是写代码。QA拿到这张表格之后,写测试用例也是手到擒来。
4. UML模板:
和状态模式UML图一样
5. 关键代码:
首先是两个枚举,一个是动作,或者说事件。一个是状态
public enum Transition
{
NullTransition = 0,
}
public enum StateID
{
NullStateID = 0,
}
状态父类
public abstract class FSMState
{
protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>();
protected StateID stateID;
public StateID ID { get { return stateID; } }
public void AddTransition(Transition trans, StateID id)
{
if (trans == Transition.NullTransition)
{
//trans不能为空
Debug.LogError("FSMState ERROR:NullTransition is not allowed for a real transition");
return;
}
if (id == StateID.NullStateID)
{
//id状态不能为空
Debug.LogError("FSMState ERROR:NullStateID is not allowed for a real ID");
return;
}
if (map.ContainsKey(trans))
{
//trans已经添加上了
Debug.LogError("FSMState ERROR:State " + stateID.ToString() + " already has transition+" + trans.ToString() + " Impossible to assign to another state");
return;
}
map.Add(trans, id);
}
public void DeleteTransition(Transition trans)
{
if (trans == Transition.NullTransition)
{
//不允许删除空值
Debug.LogError("FSMState ERROR:NullTransition is not allowed");
return;
}
if (map.ContainsKey(trans))
{
map.Remove(trans);
return;
}
//删除转换条件的时候,转换条件trans不存在
Debug.LogError("FSMState ERROR:Transition " + trans.ToString() + "passed to+" + stateID.ToString() + " was not on the state's transition list");
}
public StateID GetOutputState(Transition trans)
{
if