【unity】FSM有限状态机

前言

开发时,难免会遇到对象需要在某几个状态之间不停切换的问题,尤其是敌人对象。对于类似的问题,使用FSM有限状态机是一个不错的解决方案。今天特地抽空来总结一下FSM的相关内容。

引子

为什么要用FSM有限状态机?

小明在写敌人类时,使用了大量的if-else来控制敌人的行动,但随着敌人的行动越来越复杂,他新增的if-else也越来越多。最后逻辑糊成一坨,不堪入目。

显然,我们迫切地需要一个具有良好拓展性的,结构清晰的解决方案,让我们不至于重蹈小明的覆辙。

组成

定义一个抽象基类BaseState,其他状态类继承自该类

public abstarct class BaseState { public abstract void EnterState(NPC npc); //进入该状态时调用一次 public abstract void Action(NPC npc); //该状态需要执行的动作 public abstract void CheckSwtich(NPC npc); //检测是否要转到其他状态 public abstract void ExitState(NPC npc); //离开该状态时调用一次 }

其他类举例:AttackState

public class AttackState : BaseState { public override void EnterState(NPC npc){ /*具体实现略*/ } public override void Action(NPC npc) { /*具体实现略*/ } public override void CheckSwtich(NPC npc) { /*具体实现略*/ } public override void ExitState(NPC npc) { /*具体实现略*/ } }

其他类举例:IdleState

public class IdleState : BaseState { public override void EnterState(NPC npc){ /*具体实现略*/ } public override void Action(NPC npc) { /*具体实现略*/ } public override void CheckSwtich(NPC npc) { /*具体实现略*/ } public override void ExitState(NPC npc) { /*具体实现略*/ } }

由 FSMSystem 统一管理

public class FSMSystem { private BaseState currentState; private BaseState attackState = new AttackState(); private BaseState idleState = new IdleState(); public void Init(NPC npc) { /*具体实现略*/ } public void FSMAwake(NPC npc) { Init(npc); currentState = idleState; } public void FSMUpdate(NPC npc) { currentState.Action(npc); currentState.CheckSwtich(npc); } public void TransitionToState(BaseState state) { currentState = state; currentState.EnterState(npc); } )

我们发现各个状态没有继承自 MonoBehaviour ,无法直接挂载在游戏对象上。我们可以利用 NPC 类来管理 FSMSystem。

public class NPC : MonoBehaviour { private FSMSystem fsm; private void Awake() { fsm.FSMAwake(this); } private void Update() { fsm.FSMUpdate(this); } }

FSM的写法不唯一,像如上代码,可以取消 NPC 和 FSMSystem 之间的组合关系,将FSM中的成员直接并入 NPC 中,在某些应用场景下,这样处理可能更加适用;还可以利用字典和枚举类型,使让代码架构更加清晰......我这里的举例也只是抛砖引玉。

理解了FSM的工作机制,通过改善和优化代码,能使其更加贴合我们当前遇到的问题。

小结

1.对象在任一时刻只能处于某一种状态,而非某几个状态的叠加。
2.对象只能在有限个状态间互相切换。

利用FSM有限状态机,我们能很方便地拓展代码,如果对象有新的行为状态,我们也只需要创建新的状态类,使其继承自状态基类。这无疑降低了拓展难度。但在设计新的状态类时,要考虑清楚:对象的某一状态的入口是什么,执行过程是什么,状态出口是什么,想清楚了再动手。


__EOF__

本文作者OtusScops
本文链接https://www.cnblogs.com/OtusScops/p/16097368.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   AshScops  阅读(185)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示