[脚本]有限状态机

我们一般游戏中都是这样使用状态机的

  1. enum State_Type
  2. {
  3. GameMenu,
  4. GameLoading,
  5. GameLogic,
  6. GameOver,
  7. }
  8. void Update()
  9. {
  10.      switch(currentstate)
  11.      {
  12.     case State_Type. GameMenu:
  13.         if( 按了开始按钮 )
  14.         {
  15.             currentstate=State_Type. GameLoading;
  16.         }
  17.         if( 按了成就 )
  18.         {
  19.             currentstate=State_Type……..;
  20.         }
  21.         if(按了高分榜)
  22.         {
  23.             currentstate=State_Type……..;
  24.         }
  25.     break;
  26.              case State_Type. GameLoading:
  27.         if( 加载游戏完成 )
  28.         {
  29.             currentstate=State_Type. GameLogic;
  30.         }
  31.     break;
  32.              case State_Type. GameLogic:
  33.         if( 死了 )
  34.         {
  35.             currentstate=State_Type. GameOver;
  36.         }
  37.     break;
  38.              case State_Type. GameOver:
  39.             currentstate=State_Type. GameMenu;
  40.     break;
  41.     }
  42. }






这样写没有什么问题。不过当状态多的时候确实很头疼。


有一种方法可以解决这样的问题(有限状态机FSM)


下面是一个例子


两个实体
ActorOne
ActorTwo

第一个实体ActorOne

  1. using UnityEngine;
  2. using System.Collections;
  3. public class ActorOne  : BaseGameEntity {
  4.     //有限状态机
  5.     StateMachine<ActorOne> m_pStateMachine;
  6.     void Start () {
  7.         //设置实体的id必须唯一
  8.         SetID((int)EntityID.m_ActorOne);
  9.         //注册
  10.         m_pStateMachine = new StateMachine<ActorOne>(this);
  11.         /*
  12.             一个状态分为三个阶段
  13.                    Enter()       //进入
  14.                    Execute() //执行
  15.                    Exit()           //离开
  16.             当m_pStateMachine.SetCurrentState(ActorOne_StateOne .Instance());
  17.             会先执行ActorOne_StateOne 的Enter()方法,
  18.             然后执行ActorOne_StateOne 的Execute()方法, Execute方法会一直执行直到切换状态
  19.             当在ActorOne_StateOne(Enter(), Execute())中调用Entity.GetFSM().ChangeState(ActorOne_StateTwo.Instance());
  20.             会先执行ActorOne_StateOne 的Exit();
  21.             然后执行ActorOne_StateTwo的Enter()方法,
  22.             然后执行ActorOne_StateTwo的Execute()方法,
  23.         */
  24.         //设置当前的状态为ActorOne_StateOne
  25.         m_pStateMachine.SetCurrentState(ActorOne_StateOne .Instance());    
  26.         //设置全局的状态
  27.         m_pStateMachine.SetGlobalStateState(ActorOne_GloballState .Instance());
  28.         //实体注册到实体管理器中
  29.         EntityManager.Instance().RegisterEntity(this);
  30.     }
  31.     void Update ()
  32.     {    
  33.         //状态机update
  34.         m_pStateMachine.SMUpdate();
  35.     }
  36.     public StateMachine<ActorOne> GetFSM ()
  37.     {
  38.         //获得状态机
  39.         return m_pStateMachine;
  40.     }
  41.     public override bool HandleMessage (Telegram telegram)
  42.     {
  43.         //解析消息
  44.         return     m_pStateMachine.HandleMessage(telegram);
  45.     }
  46. }






第2个实体ActorTwo

  1. using UnityEngine;
  2. using System.Collections;
  3. public class ActorTwo  : BaseGameEntity {
  4.     StateMachine<ActorTwo> m_pStateMachine;
  5.     public Transform TwoTransform;
  6.     // Use this for initialization
  7.     void Start () {
  8.         // set id
  9.         SetID((int)EntityID.m_ActorTwo);
  10.         m_pStateMachine = new StateMachine<ActorTwo>(this);
  11.         m_pStateMachine.SetCurrentState(ActorTwo_StateOne.Instance());    
  12.         m_pStateMachine.SetGlobalStateState(ActorTwo_GloballState.Instance());
  13.         EntityManager.Instance().RegisterEntity(this);
  14.     }
  15.     void Update ()
  16.     {    
  17.         m_pStateMachine.SMUpdate();
  18.     }
  19.     public StateMachine<ActorTwo> GetFSM ()
  20.     {
  21.         return m_pStateMachine;
  22.     }
  23.     public override bool HandleMessage (Telegram telegram)
  24.     {
  25.         return     m_pStateMachine.HandleMessage(telegram);
  26.     }
  27. }










ActorOneState 第一个实体的状态

  1. using UnityEngine;
  2. using System.Collections;
  3. /*
  4. 状态分为两种
  5. 1全局状态 一般情况下会一直执行 可以负责调度
  6. 2普通状态 也就是上面的GameMenu,GameLoading,GameLogic,GameOver,
  7. */
  8. //全局状态
  9. public class ActorOne_GloballState :State<ActorOne >
  10. {
  11.     private static ActorOne_GloballState instance;
  12.     public static ActorOne_GloballState Instance ()
  13.     {
  14.         if (instance == null)
  15.             instance = new ActorOne_GloballState ();
  16.         return instance;
  17.     }
  18.     //当状态被调用是执行一次
  19.     public override void Enter (ActorOne Entity)
  20.     {
  21.         //base.Enter (Entity);
  22.     }
  23.     //相当于update方法
  24.     public override void Execute (ActorOne Entity)
  25.     {
  26.         //base.Execute (Entity);    
  27.     }
  28.     //状态退出是被调用
  29.     public override void Exit (ActorOne Entity)
  30.     {
  31.         //base.Exit (Entity);
  32.     }
  33.     //接收消息
  34.     public override bool OnMessage (ActorOne Entity, Telegram telegram)
  35.     {
  36.         return false;
  37.     }
  38. }
  39. public class ActorOne_StateOne : State<ActorOne>
  40. {
  41.     private static ActorOne_StateOne instance;
  42.     public static ActorOne_StateOne Instance ()
  43.     {
  44.         if (instance == null)
  45.             instance = new ActorOne_StateOne ();
  46.         return instance;
  47.     }
  48.     public override void Enter (ActorOne Entity)
  49.     {
  50.         //base.Enter (Entity);
  51.     }
  52.     public override void Execute (ActorOne Entity)
  53.     {
  54.         /*
  55.         调用实体的GetFSM()获得状态机器
  56.         在调用状态机的ChangeState(ActorOne_StateTwo.Instance())
  57.         改变状态
  58.         这里是从当前状态ActorOne_StateOne切换到ActorOne_StateTwo状态;
  59.         */
  60.         Entity.GetFSM().ChangeState(ActorOne_StateTwo.Instance());
  61.         //base.Execute (Entity);
  62.     }
  63.     public override void Exit (ActorOne Entity)
  64.     {
  65.         //base.Exit (Entity);
  66.     }
  67.     public override bool OnMessage (ActorOne Entity, Telegram telegram)
  68.     {
  69.         return false;
  70.     }
  71. }
  72. public class ActorOne_StateTwo : State<ActorOne>
  73. {
  74.     private static ActorOne_StateTwo instance;
  75.     public static ActorOne_StateTwo Instance ()
  76.     {
  77.         if (instance == null)
  78.             instance = new ActorOne_StateTwo ();
  79.         return instance;
  80.     }
  81.     public override void Enter (ActorOne Entity)
  82.     {
  83.         /*
  84.             MessageDispatcher.Instance().DispatchMessage();用于在实体间传送消息
  85.             下面代码的意思就是
  86.             发送消息给ActorTwo,延迟5秒发送,消息的类型msg_oneMessage
  87.         */
  88.         MessageDispatcher.Instance().DispatchMessage(
  89.                 5f, // delay 消息的延迟时间
  90.                                 Entity.ID(),        // sender 发送者
  91.                                (int)EntityID.m_ActorTwo,            // receiver 接收者
  92.                                (int)message_type.msg_oneMessage,    //message
  93.                                 Entity);  //附加信息
  94.         //base.Enter (Entity);
  95.     }
  96.     public override void Execute (ActorOne Entity)
  97.     {
  98.         //base.Execute (Entity);
  99.     }
  100.     public override void Exit (ActorOne Entity)
  101.     {
  102.         //base.Exit (Entity);
  103.     }
  104.     public override bool OnMessage (ActorOne Entity, Telegram telegram)
  105.     {
  106.         /*
  107.             接收ActorTwo发送过来的消息(message_type.msg_twoMessage)
  108.         */
  109.         if(telegram.Msg == (int)message_type.msg_twoMessage)
  110.         {
  111.             /*
  112.                 接收成功
  113.             */
  114.             return true;
  115.         }
  116.         return false;
  117.     }
  118. }






ActorTwo 第2个实体的具体状态

  1. using UnityEngine;
  2. using System.Collections;
  3. public class ActorTwo_GloballState : State<ActorTwo>
  4. {
  5.     private static ActorTwo_GloballState instance;
  6.     public static ActorTwo_GloballState Instance ()
  7.     {
  8.         if (instance == null)
  9.             instance = new ActorTwo_GloballState ();
  10.         return instance;
  11.     }
  12.     public override void Enter (ActorTwo Entity)
  13.     {
  14.         //base.Enter (Entity);
  15.     }
  16.     public override void Execute (ActorTwo Entity)
  17.     {
  18.         //base.Execute (Entity);    
  19.     }
  20.     public override void Exit (ActorTwo Entity)
  21.     {
  22.         //base.Exit (Entity);
  23.     }
  24.     //消息处理
  25.     public override bool OnMessage (ActorTwo Entity, Telegram telegram)
  26.     {
  27.         /*
  28.             接收ActorOne发送来的消息(message_type.msg_oneMessage)
  29.         */
  30.         if (telegram.Msg == (int)message_type.msg_oneMessage) {
  31.             /*
  32.                 接收成功处理消息从当前状态切换到ActorTwo_StateTwo状态;
  33.             */
  34.             Entity.GetFSM ().ChangeState (ActorTwo_StateTwo.Instance ());
  35.             return true;
  36.         }
  37.         return false;
  38.     }
  39. }
  40. public class ActorTwo_StateOne : State<ActorTwo>
  41. {
  42.     private static ActorTwo_StateOne instance;
  43.     public static ActorTwo_StateOne Instance ()
  44.     {
  45.         if (instance == null)
  46.             instance = new ActorTwo_StateOne ();
  47.         return instance;
  48.     }
  49.     public override void Enter (ActorTwo Entity)
  50.     {
  51.         //base.Enter (Entity);
  52.     }
  53.     public override void Execute (ActorTwo Entity)
  54.     {
  55.         //base.Execute (Entity);
  56.     }
  57.     public override void Exit (ActorTwo Entity)
  58.     {
  59.         //base.Exit (Entity);
  60.     }
  61.     public override bool OnMessage (ActorTwo Entity, Telegram telegram)
  62.     {
  63.         return false;
  64.     }
  65. }
  66. public class ActorTwo_StateTwo : State<ActorTwo>
  67. {
  68.     private static ActorTwo_StateTwo instance;
  69.     public static ActorTwo_StateTwo Instance ()
  70.     {
  71.         if (instance == null)
  72.             instance = new ActorTwo_StateTwo ();
  73.         return instance;
  74.     }
  75.     public override void Enter (ActorTwo Entity)
  76.     {
  77.         /*
  78.             发送消息给ActorOne,延迟1秒,消息类型msg_twoMessage
  79.         */
  80.         MessageDispatcher.Instance ().DispatchMessage(
  81.                 1f,
  82.                 Entity.ID (),
  83.                 (int)EntityID.m_ActorOne,
  84.                 (int)message_type.msg_twoMessage,
  85.                 Entity);
  86.         //base.Enter (Entity);        
  87.     }
  88.     public override void Execute (ActorTwo pMiner)
  89.     {
  90.         //base.Execute (Entity);
  91.     }
  92.     public override void Exit (ActorTwo Entity)
  93.     {
  94.         //base.Exit (Entity);
  95.     }
  96.     public override bool OnMessage (ActorTwo Entity, Telegram telegram)
  97.     {
  98.         return false;
  99.     }
  100. }






这样看起来就很清晰了修改起来只要修改具体的状态类就行了。


在使用的时候最好写一个状态表


实体一
当前状态                             条件                                            目标状态/实体
睡觉                           被打醒了                                         狂暴
狂暴                        无条件                               投降             

posted @ 2012-03-14 11:20  渡蓝  阅读(564)  评论(0)    收藏  举报