Unity中实现一个状态机

维基百科:有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

本文参照quick-cocos中的StateMachine, 实现了Unity版本的有限状态机。


实现思路:

  1. 创建一个状态机对象
public class StateMachine : MonoBehaviour {
    ...
}
  1. 初始化状态机信息,包括事件和回调函数。
// 事件
public class SMEvent
{
    readonly string name;
    readonly List<string> froms;
    readonly string to;

    public string Name { get { return name; } }
    public List<string> Froms { get { return froms; } }
    public string To { get { return to; } }

    public SMEvent(string _name, List<string> _froms, string _to)
    {
        name = _name;
        froms = _froms;
        to = _to;
    }
}

// 回调函数
Dictionary<string, Func<SMEvent, bool>> _callbacks;
  1. 切换状态通过执行事件实现。
public int DoEvent(string name){ ... }
  1. 执行事件的条件判断
public bool IsReady(){...} :返回状态机是否就绪
public string GetState(){...} :返回当前状态
public bool IsState(string state){...} :判断当前状态是否是参数state状态
public bool CanDoEvent(string eventName){...}:当前状态如果能完成eventName对应的event的状态转换,则返回true
public bool CanNotDoEvent(string eventName){...} :当前状态如果不能完成eventName对应的event的状态转换,则返回true
public bool IsFinishedState(){...}:当前状态如果是最终状态,则返回true
  1. 执行回调函数

// 在事件EVENT开始前被激活
private bool BeforeThisEvent(SMEvent smEvent) {...}


// 在离开旧状态STATE时被激活
private bool LeaveThisEvent(SMEvent smEvent) {...}


// 在进入新状态STATE时被激活
private bool EnterThisEvent(SMEvent smEvent) {...}


// 在事件EVENT结束后被激活
private bool AfterThisEvent(SMEvent smEvent) {...}


// 在任何事件开始前被激活
private bool BeforeAnyEvent(SMEvent smEvent) {...}

// 在任何事件结束后被激活
private bool AfterAnyEvent(SMEvent smEvent) {...}

// 在进入任何状态时被激活
private bool EnterAnyState(SMEvent smEvent) {...}


// 在离开任何状态时被激活
private bool LeaveAnyState(SMEvent smEvent) {...}

// 当状态发生改变的时候被激活
private bool ChangeAnyState(SMEvent smEvent) {...}

使用示例:

// 创建一个状态机实例
StateMachine fsm = gameObject.AddComponent<StateMachine>();

// 添加事件和状态
List<SMEvent> events = new List<SMEvent>();
events.Add(new SMEvent("move", new List<string> { "idle", "jump"}, "walk"));
events.Add(new SMEvent("attack", new List<string> { "idle", "walk" }, "jump"));
events.Add(new SMEvent("normal", new List<string> { "walk", "jump"}, "idle"));
events.Add(new SMEvent("lie", new List<string> { "move", "idle"}, "falldown"));

// 添加回调函数
Func<SMEvent, bool> onenteridle = x => Walk(x);
Func<SMEvent, bool> onenterwalk = x => Jump(x);
Func<SMEvent, bool> onenterjump = x => Idle(x);
Func<SMEvent, bool> onenterlie = x => FallDown(x);

Dictionary<string, Func<SMEvent, bool>> callbacks = new Dictionary<string, Func<SMEvent, bool>>();
callbacks.Add("onenternormal", onenteridle);
callbacks.Add("onentermove", onenterwalk);
callbacks.Add("onenterattack", onenterjump);
callbacks.Add("onenterlie", onenterlie);

// 初始化状态机
string initial = "idle";
fsm.SetupState(events, callbacks, initial, "", false);;

// 回调
private bool Walk(SMEvent smEvent) {
    Debug.LogError("Walk");
    return true;
}

private bool Jump(SMEvent smEvent)
{
    Debug.LogError("Jump");
    return true;
}

private bool Idle(SMEvent smEvent)
{
    Debug.LogError("Idle");
    return true;
}

private bool FallDown(SMEvent smEvent)
{
    Debug.LogError("FallDown");
    return true;
}

实例地址:

https://github.com/MagicDavid20/UnityFSM/tree/master/fsm

其它:

  1. 状态和事件名可以通过配置表或者枚举来实现
  2. Walk,Jump等具体的实现可以通过状态模式, 移动指针地址实现。

如有错误,欢迎指出。

email:dxmdxm1992#gmail.com

blog: http://blog.csdn.net/david_dai_1108

猜你喜欢

转载自blog.csdn.net/david_dai_1108/article/details/76167729