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版本实现