基于unity3d(C#)的有限状态机设计(二)

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

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 m_pStateMachine;
    void Start () {
        //设置实体的id必须唯一
        SetID((int)EntityID.m_ActorOne);
 
        //注册
        m_pStateMachine = new StateMachine(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 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 m_pStateMachine;
 
    public Transform TwoTransform;
 
    // Use this for initialization
    void Start () {
 
 
        // set id 
        SetID((int)EntityID.m_ActorTwo);
 
        m_pStateMachine = new StateMachine(this);
 
        m_pStateMachine.SetCurrentState(ActorTwo_StateOne.Instance());    
 
 
        m_pStateMachine.SetGlobalStateState(ActorTwo_GloballState.Instance());
        EntityManager.Instance().RegisterEntity(this);
    }
 
    void Update ()
    {    
 
        m_pStateMachine.SMUpdate();
    }
 
 
    public StateMachine 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
{
    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
{
    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
{
    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
{
    private static ActorTwo_GloballState instance;
    public static ActorTwo_GloballState Instance ()
    {
        if (instance == null)
            instance = new ActorTwo_GloballState ();
 
        return instance;
    }
 
 
 
 
    public override void Enter (ActorTwo Entity)
    {
        //base.Enter (Entity);
    }
 
 
    public override void Execute (ActorTwo Entity)
    {
        //base.Execute (Entity);    
    }
 
 
    public override void Exit (ActorTwo Entity)
    {
        //base.Exit (Entity);
    }
 
 
    //消息处理
    public override bool OnMessage (ActorTwo Entity, Telegram telegram)
    {
        /*
            接收ActorOne发送来的消息(message_type.msg_oneMessage)
        */
        if (telegram.Msg == (int)message_type.msg_oneMessage) {
            /*
                接收成功处理消息从当前状态切换到ActorTwo_StateTwo状态;
            */
            Entity.GetFSM ().ChangeState (ActorTwo_StateTwo.Instance ());
            return true;
        }
 
        return false;
    }
}
 
 
public class ActorTwo_StateOne : State
{
    private static ActorTwo_StateOne instance;
    public static ActorTwo_StateOne Instance ()
    {
        if (instance == null)
            instance = new ActorTwo_StateOne ();
 
        return instance;
    }
 
 
    public override void Enter (ActorTwo Entity)
    {
        //base.Enter (Entity);
    }
 
 
    public override void Execute (ActorTwo Entity)
    {
        //base.Execute (Entity);
    }
 
 
    public override void Exit (ActorTwo Entity)
    {
        //base.Exit (Entity);
    }
 
 
    public override bool OnMessage (ActorTwo Entity, Telegram telegram)
    {
        return false;
    }
}
 
 
 
 
public class ActorTwo_StateTwo : State
{
    private static ActorTwo_StateTwo instance;
    public static ActorTwo_StateTwo Instance ()
    {
        if (instance == null)
            instance = new ActorTwo_StateTwo ();
 
        return instance;
    }
 
 
    public override void Enter (ActorTwo Entity)
    {
        /*
            发送消息给ActorOne,延迟1秒,消息类型msg_twoMessage
        */
        MessageDispatcher.Instance ().DispatchMessage(
                1f, 
                Entity.ID (), 
                (int)EntityID.m_ActorOne, 
                (int)message_type.msg_twoMessage, 
                Entity);
 
 
        //base.Enter (Entity);        
    }
 
 
    public override void Execute (ActorTwo pMiner)
    {
        //base.Execute (Entity);
 
 
    }
 
 
    public override void Exit (ActorTwo Entity)
    {
        //base.Exit (Entity);
    }
 
 
    public override bool OnMessage (ActorTwo Entity, Telegram telegram)
    {
 
        return false;
    }
}


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


实体一
当前状态                             条件                                            目标状态/实体
睡觉                           被打醒了                                         狂暴
狂暴                        无条件                               投降                             
推荐一本书 游戏人工智能编程案例精粹


代码还有例子包里有

描述:有限状态机
附件:    FSM.unitypackage (26 K) 下载次数:243


(来自:http://game.ceeger.com/forum/read.php?tid=817)




你可能感兴趣的:(Unity3D)