有限状态机(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) { }}
   复制代码
 五
最后将人物类中各个运动方法绑定到界面的按钮上面,然后运行,发现可以做到人物动作改变了
效果:
评论