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

来源:互联网 发布:mac pro 13寸高清壁纸 编辑:程序博客网 时间:2024/06/08 19:19

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


using System;using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public abstract class FSM<T> : MonoBehaviour {    protected State state;       public class State {        public System.Action OnEnter = delegate { };        public System.Action OnTick = delegate { };        public System.Action OnExit = delegate { };        public System.Action<T, object[]> SetTrigger = delegate { };        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;    }}