分享一个unity3d 有限状态机 例子来供大家学习、参考和交流,因为我们一般在游戏中都会这样使用状态机,代码如下:。
- enum State_Type
- {
- GameMenu,
- GameLoading,
- GameLogic,
- GameOver,
- }
- void Update()
- {
- switch(currentstate)
- {
- case State_Type. GameMenu:
- if( 按了开始按钮 )
- {
- currentstate=State_Type. GameLoading;
- }
- if( 按了成就 )
- {
- currentstate=State_Type……..;
- }
- if(按了高分榜)
- {
- currentstate=State_Type……..;
- }
- break;
- case State_Type. GameLoading:
- if( 加载游戏完成 )
- {
- currentstate=State_Type. GameLogic;
- }
- break;
- case State_Type. GameLogic:
- if( 死了 )
- {
- currentstate=State_Type. GameOver;
- }
- break;
- case State_Type. GameOver:
- currentstate=State_Type. GameMenu;
- break;
- }
- }
这样写没有什么问题。不过当状态多的时候确实很头疼。
有一种方法可以解决这样的问题(有限状态机FSM)
下面是一个例子
两个实体
ActorOne
ActorTwo
第一个实体ActorOne
- using UnityEngine;
- using System.Collections;
- public class ActorOne : BaseGameEntity {
- //有限状态机
- StateMachine<ActorOne> m_pStateMachine;
- void Start () {
- //设置实体的id必须唯一
- SetID((int)EntityID.m_ActorOne);
- //注册
- m_pStateMachine = new StateMachine<ActorOne>(this);
- /*
- 一个状态分为三个阶段
- Enter() //进入
- Execute() //执行
- Exit() //离开
- 当m_pStateMachine.SetCurrentState(ActorOne_StateOne .Instance());
- 会先执行ActorOne_StateOne 的Enter()方法,
- 然后执行ActorOne_StateOne 的Execute()方法, Execute方法会一直执行直到切换状态
- 当在ActorOne_StateOne(Enter(), Execute())中调用Entity.GetFSM().ChangeState(ActorOne_StateTwo.Instance());
- 会先执行ActorOne_StateOne 的Exit();
- 然后执行ActorOne_StateTwo的Enter()方法,
- 然后执行ActorOne_StateTwo的Execute()方法,
- */
- //设置当前的状态为ActorOne_StateOne
- m_pStateMachine.SetCurrentState(ActorOne_StateOne .Instance());
- //设置全局的状态
- m_pStateMachine.SetGlobalStateState(ActorOne_GloballState .Instance());
- //实体注册到实体管理器中
- EntityManager.Instance().RegisterEntity(this);
- }
- void Update ()
- {
- //状态机update
- m_pStateMachine.SMUpdate();
- }
- public StateMachine<ActorOne> GetFSM ()
- {
- //获得状态机
- return m_pStateMachine;
- }
- public override bool HandleMessage (Telegram telegram)
- {
- //解析消息
- return m_pStateMachine.HandleMessage(telegram);
- }
- }
第2个实体ActorTwo
- using UnityEngine;
- using System.Collections;
- public class ActorTwo : BaseGameEntity {
- StateMachine<ActorTwo> m_pStateMachine;
- public Transform TwoTransform;
- // Use this for initialization
- void Start () {
-
- // set id
- SetID((int)EntityID.m_ActorTwo);
-
- m_pStateMachine = new StateMachine<ActorTwo>(this)
- m_pStateMachine.SetCurrentState(ActorTwo_StateOne.Instance());
-
- m_pStateMachine.SetGlobalStateState(ActorTwo_GloballState.Instance());
- EntityManager.Instance().RegisterEntity(this);
- }
-
- void Update ()
- {
- m_pStateMachine.SMUpdate();
- }
- public StateMachine<ActorTwo> GetFSM ()
- {
- return m_pStateMachine;
- }
- public override bool HandleMessage (Telegram telegram)
- {
- return m_pStateMachine.HandleMessage(telegram);
- }
- }
ActorOneState 第一个实体的状态
- using UnityEngine;
- using System.Collections;
- /*
- 状态分为两种
- 1全局状态 一般情况下会一直执行 可以负责调度
- 2普通状态 也就是上面的GameMenu,GameLoading,GameLogic,GameOver,
- */
- //全局状态
- public class ActorOne_GloballState :State<ActorOne >
- {
- private static ActorOne_GloballState instance;
- public static ActorOne_GloballState Instance ()
- {
- if (instance == null)
- instance = new ActorOne_GloballState ();
- return instance;
- }
- //当状态被调用是执行一次
- public override void Enter (ActorOne Entity)
- {
- //base.Enter (Entity);
- }
- //相当于update方法
- public override void Execute (ActorOne Entity)
- {
- //base.Execute (Entity);
- }
- //状态退出是被调用
- public override void Exit (ActorOne Entity)
- {
- //base.Exit (Entity);
- }
- //接收消息
- public override bool OnMessage (ActorOne Entity, Telegram telegram)
- {
- return false;
- }
- }
- public class ActorOne_StateOne : State<ActorOne>
- {
- private static ActorOne_StateOne instance;
- public static ActorOne_StateOne Instance ()
- {
- if (instance == null)
- instance = new ActorOne_StateOne ();
- return instance;
- }
- public override void Enter (ActorOne Entity)
- {
- //base.Enter (Entity);
- }
- public override void Execute (ActorOne Entity)
- {
- /*
- 调用实体的GetFSM()获得状态机器
- 在调用状态机的ChangeState(ActorOne_StateTwo.Instance())
- 改变状态
- 这里是从当前状态ActorOne_StateOne切换到ActorOne_StateTwo状态;
- */
- Entity.GetFSM().ChangeState(ActorOne_StateTwo.Instance());
- //base.Execute (Entity);
- }
-
- public override void Exit (ActorOne Entity)
- {
- //base.Exit (Entity);
- }
-
- public override bool OnMessage (ActorOne Entity, Telegram telegram)
- {
- return false;
- }
- }
-
- public class ActorOne_StateTwo : State<ActorOne>
- {
- private static ActorOne_StateTwo instance;
- public static ActorOne_StateTwo Instance ()
- {
- if (instance == null)
- instance = new ActorOne_StateTwo ();
- return instance;
- }
- public override void Enter (ActorOne Entity)
- {
- /*
- MessageDispatcher.Instance().DispatchMessage();用于在实体间传送消息
- 下面代码的意思就是
- 发送消息给ActorTwo,延迟5秒发送,消息的类型msg_oneMessage
- */
- MessageDispatcher.Instance().DispatchMessage(
- 5f, // delay 消息的延迟时间
- Entity.ID(), // sender 发送者
- (int)EntityID.m_ActorTwo, // receiver 接收者
- (int)message_type.msg_oneMessage, //message
- Entity); //附加信息
- //base.Enter (Entity);
- }
- public override void Execute (ActorOne Entity)
- {
- //base.Execute (Entity);
- }
- public override void Exit (ActorOne Entity)
- {
- //base.Exit (Entity);
- }
- public override bool OnMessage (ActorOne Entity, Telegram telegram)
- {
- /*
- 接收ActorTwo发送过来的消息(message_type.msg_twoMessage)
- */
- if(telegram.Msg == (int)message_type.msg_twoMessage)
- {
- /*
- 接收成功
- */
- return true;
- }
- return false;
- }
- }
-
- ActorTwo 第2个实体的具体状态
- using UnityEngine;
- using System.Collections;
- public class ActorTwo_GloballState : State<ActorTwo>
- {
- private static ActorTwo_GloballState instance;
- public static ActorTwo_GloballState Instance ()
- {
- if (instance == null)
- instance = new ActorTwo_GloballState ();
- return instance;
- }