写点什么

Cocos Creator 学习の有限状态机

作者:空城机
  • 2022 年 5 月 13 日
  • 本文字数:1997 字

    阅读完需:约 7 分钟

Cocos Creator学习の有限状态机

有限状态机(Finite State Machine)

其在任意时刻都处于有限状态集合中的某一状态。当其获得一个改变信息时,将从当前状态转换到另一个状态,或者仍然保持在当前状态


拿游戏中的人物举例:就是人物无时无刻都是处于某种状态之中的


具体实现时,可以把角色不同的行为分成不同的状态,然后给某一状态写入方法。通过状态机去进行人物不同状态之间的切换


可参考学习:https://www.bilibili.com/video/BV14i4y1o7YF?p=83

使用状态机的理由

在实际开发中,人物可能会有很多状态动作,如果将这些状态动作都写着人物类当中,代码会非常冗杂,并且不好管理。一个对象的状态越多、发生的事件越多,就越适合采用有限状态机的写法

实例

实例结构

此结构也可以看完后面的步骤再回过来看


cocos creator页面中先拖放一个精灵节点,为这个精灵节点创建一些像站立、跑步、攻击之类的animation动画。 然后再在旁边设置一系列动作切换的按钮。


创建有限状态机的管理类FSMManager.ts和状态类FSMState.ts


首先在状态类中,定义StateID状态 ID,以及stateComponent状态的拥有者,还有此状态所属的状态管理器fsmManager

export default class FSMState {    // 状态ID    StateID: number = -1;    // 所属的状态拥有者    stateComponent: cc.Component;    // 所属的状态管理器    fsmManager: FSMManager = null;
constructor(StateID: number, stateComponent: cc.Component, fsmManager: FSMManager) { this.StateID = StateID; this.stateComponent = stateComponent; this.fsmManager = fsmManager; } // 进入状态 OnEnter() { } // 状态更新 OnUpdate() { }}
复制代码


在管理类当中,需要定义状态列表stateList属性和当前的状态 ID currentID属性,并且创建改变状态和更新调用方法

export default class FSMManager  {    // 状态列表    stateList: FSMState[] = [];    // 当前状态ID    currentID: number = -1;
// 改变状态 changeState(stateID: number) { this.currentID = stateID; // 调用新状态id的enter方法 this.stateList[this.currentID].OnEnter(); } // 更新调用 OnUpdate() { if (this.currentID != -1) { this.stateList[this.currentID].OnUpdate(); } }}
复制代码

按照以上两个步骤,FSM 有限状态机的基础类就已经创建完毕了,接下来进行人物类personControl以及各个动作类的单独编写。 各个基础动作了都继承自状态类FSMState.ts

然后在站立、跑步、攻击各个类中重写OnEnter进入状态方法。


以下是跑步状态类,其他动作类都与其类似。

export default class runState extends FSMState {    // 进入状态    OnEnter() {        this.stateComponent.getComponent(cc.Animation).play('heroRun');    }    // 状态更新    OnUpdate() { }}
复制代码

personControl人物类中,生成一个状态机管理器的实例,将现有的动作类生成实例,然后加入在此实例中的状态列表stateList


然后为此人物类创建运动方法,运动方法中只需要调用状态管理类中的changeState改变状态方法,即可切换人物的状态

PS: 因为一个人物的动作状态可能会有很多,所以可以使用枚举和数组先存储好这些状态的编号以及类,然后在生成状态实例时使用for循环进行生成


// 创建状态枚举enum PersonState {    stand = 0,    run,    attack1,    attack2,    attack3}
let stateClassArr = [ standState, runState, attack1, attack2, attack3]
@ccclassexport default class personControl extends cc.Component { // 动画 ani: cc.Animation; // 状态机 fsmManager: FSMManager; // onLoad () {} start () { this.ani = this.node.getComponent(cc.Animation); this.fsmManager = new FSMManager(); // 创建几个动作状态 for(let i in PersonState) { let index = Number(i); if (!isNaN(index)) { this.fsmManager.stateList.push(new stateClassArr[index](index, this, this.fsmManager)); } } }
// 站立 stand() { this.fsmManager.changeState(PersonState.stand); } // 跑步 run() { this.fsmManager.changeState(PersonState.run); } // 攻击 attack1() { this.fsmManager.changeState(PersonState.attack1); } attack2() { this.fsmManager.changeState(PersonState.attack2); } attack3() { this.fsmManager.changeState(PersonState.attack3); } update (dt) { }}
复制代码

最后将人物类中各个运动方法绑定到界面的按钮上面,然后运行,发现可以做到人物动作改变了


效果:


发布于: 刚刚阅读数: 4
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步

评论

发布
暂无评论
Cocos Creator学习の有限状态机_Cocos_空城机_InfoQ写作社区