最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
unity3d 有限状态机 例子
本文将分享一个Unity3D有限状态机的例子,供大家学习、参考和交流。在游戏开发中,状态机是一种常用的设计模式,下面我们先来看一个简单的状态机实现示例,代码如下:
// 定义状态类型的枚举
enum State_Type
{
GameMenu,
GameLoading,
GameLogic,
GameOver
}
// 当前状态
State_Type currentstate;
void Update()
{
switch (currentstate)
{
case State_Type.GameMenu:
// 模拟按了开始按钮
if (Input.GetKeyDown(KeyCode.Space))
{
currentstate = State_Type.GameLoading;
}
// 模拟按了成就
if (Input.GetKeyDown(KeyCode.A))
{
// 这里应补充具体状态
// currentstate = State_Type......;
}
// 模拟按了高分榜
if (Input.GetKeyDown(KeyCode.H))
{
// 这里应补充具体状态
// currentstate = State_Type......;
}
break;
case State_Type.GameLoading:
// 模拟加载游戏完成
if (/* 加载完成的条件 */ true)
{
currentstate = State_Type.GameLogic;
}
break;
case State_Type.GameLogic:
// 模拟角色死亡
if (/* 死亡的条件 */ true)
{
currentstate = State_Type.GameOver;
}
break;
case State_Type.GameOver:
currentstate = State_Type.GameMenu;
break;
}
}
这种简单的switch语句实现的状态机在状态较少时是可行的,但当状态数量增多时,代码会变得难以维护和扩展,会让人头疼。接下来,我们介绍一种使用有限状态机(FSM)的方法来解决这个问题。
两个实体的有限状态机实现
实体一: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);
}
}
实体二: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);
}
}
ActorOne的状态实现
全局状态:ActorOne_GloballState
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;
}
}
普通状态:ActorOne_StateOne
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;
}
}
普通状态:ActorOne_StateTwo
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的全局状态
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;
}
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;
}
}
通过上述代码,我们展示了如何使用有限状态机来管理实体的状态,这种方式可以让代码更加模块化、可维护和可扩展,避免了简单switch语句在状态增多时带来的问题。在实际开发中,你可以根据具体需求对状态机和状态进行进一步的扩展和优化。