Unity中状态机模式的简单封装

Posted stalendp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity中状态机模式的简单封装相关的知识,希望对你有一定的参考价值。

游戏中的逻辑少不了用状态机。但是面对复杂的状态(比如战斗角色控制,复杂的UI状态控制等),用状态机模式是最合适不过的了。结合C#的特点,我对状态机模式进行了简化。

完善的fsm:

public abstract class FSM<T> : MonoBehaviour 
    static System.Action FuncVoid = () => ;
    protected static System.Action<T, object> DefaultTrigger = (t, p) =>  ;

    public State state  get; private set; 
    public string Name;

    public void SetDefaultTrigger(System.Action<T, object> _SetTrigger) 
        DefaultTrigger = _SetTrigger;
    

    public class State 
        public System.Action OnEnter = FuncVoid;
        public System.Action OnTick = FuncVoid;
        public System.Action OnExit = FuncVoid;
        public System.Action<T, object> SetTrigger = DefaultTrigger;
        public string Name  get; private set; 

        public State(string name) 
            Name = name;
        
    

    public void setState(State _state) 
        state.OnExit();
        state = _state;
        Name = state.Name;
        state.OnEnter();
    

    protected void doStart() 
        if (state == null) 
            state = initState();
            state.OnEnter();
            StartCoroutine(OnTick());
        
    

    IEnumerator OnTick() 
        while (true) 
            state.OnTick();
            yield return null;
        
    

    protected abstract State initState();

下面是个例子:

public abstract class FSMManager<T> 
    public State current  get; protected set; 

    public abstract void Start();

    public class State 
        private string name;
        public System.Action OnEnter = FuncVoid;
        public System.Action OnTick = FuncVoid;
        public System.Action OnExit = FuncVoid;
        public System.Action<T, object[]> SetTrigger = FuncVoid2;
    

    public static void FuncVoid()  
    public static void FuncVoid2(T type, object[] ps)  


    public void SetTrigger(T type, Object[] ps = null) 
        current.SetTrigger(type, ps);
    

    public void SetState(State state) 
        current.OnExit();
        current = state;
        current.OnEnter();
    

    public void OnTick() 
        current.OnTick();
    

使用:

public class MyFSM : FSMManager<MyFSM.Type> 
    public enum Type 
        Type1,
        Type2,
        Typ3
    
    public int count = 0;
    public State state1, state2;

    public MyFSM() 
        current = state1;
    

    public override void Start() 
        current = state1;
        state1.OnEnter();
    

 

public string test1= "111", test2 = "222";
public MyFSM fsm;
[Test]
public void NewEditModeTestSimplePasses() 
    // Use the Assert class to test conditions.

    fsm = new MyFSM() 
        state1 = new FSMManager<MyFSM.Type>.State() 
            OnEnter = delegate 
                Debug.Log("===>> " + fsm.count);
                if (fsm.count++ < 2) 
                    fsm.SetState(fsm.state1);
                 else 
                    fsm.SetState(fsm.state2);
                
            ,
        ,
        state2 = new FSMManager<MyFSM.Type>.State() 
            OnEnter = delegate 
                Debug.Log("===>>>" + test2);
            
        ,
    ;
    fsm.Start();

 

================ 另外的例子 ==================

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public abstract class FSM<T> : MonoBehaviour 
    static void FuncVoid()  
    static void FuncVoid2(T type, object[] ps)  

    protected State state;

    public class State 
        public System.Action OnEnter = FuncVoid;
        public System.Action OnTick = FuncVoid;
        public System.Action OnExit = FuncVoid;
        public System.Action<T, object[]> SetTrigger = FuncVoid2;
        public int param;
    

    public void setState(State _state) 
        state.OnExit();
        state = _state;
        state.OnEnter();
    

    protected void doStart(State ss) 
        state = initState();
        StartCoroutine(OnTick());
    

    IEnumerator OnTick() 
        while (true) 
            state.OnTick();
            yield return null;
        
    

    protected abstract State initState();


public class UILoading : FSM<UILoading.MyEvent> 
    public enum MyEvent 
        Trig1,
        Trig2,
        Trig3
    
    State state1, state2;

    public Animator anim;

    public Button btnLocal;
    public Button btnOnline;
    public Button btnOptions;


    void printOK(string who) 
        Debug.LogError("=====OKOKOK!! " + who);
    

    private void Awake() 
        doStart(state1);

        btnLocal.onClick.AddListener(delegate 
            state.SetTrigger(MyEvent.Trig1, null);
        );

        btnOnline.onClick.AddListener(delegate 
            state.SetTrigger(MyEvent.Trig2, null);
        );
        anim.StopPlayback();
        btnOptions.onClick.AddListener(delegate 
            anim.StartPlayback();
            Debug.LogError("======");
        );

    

    protected override State initState() 
        state1 = new State() 
            param = 7,
            OnEnter = delegate 
                state1.param = 5;
                printOK("state1");
            ,
            OnTick = delegate 
                state1.param--;
                Debug.LogError("State1 tick : " + state1.param);

                if (state1.param <= 0) 
                    setState(state2);
                
            ,
            OnExit = delegate 
                Debug.LogError("<<< State1 exit");
            
        ;
        state2 = new State() 
            OnEnter = delegate 
                printOK("state2");
            ,
            OnTick = delegate 
                Debug.LogError("state2 Tick");
            ,
            OnExit = delegate 
                Debug.LogError("<<< State2 exit");
            ,
            SetTrigger = (e, ps) => 
                switch (e) 
                    case MyEvent.Trig1:
                        setState(state1);
                        break;
                    case MyEvent.Trig2:
                        printOK("!!!!!");
                        break;
                
            
        ;
        return state1;
    

 

 

 

 

 

以上是关于Unity中状态机模式的简单封装的主要内容,如果未能解决你的问题,请参考以下文章

游戏设计模式之三 状态模式有限状态机 & Unity版本实现

动画状态机是有限状态机还是行为树

游戏设计模式之三 状态模式有限状态机 & Unity版本实现

unity 状态机 + svn + 码云 上篇

Unity c#

Unity FSM 有限状态机