##creator组件化探索 (一) —— 轻量级状态机组件
作者: 白羊wss
###前言
组件化是很好整理自己代码业务逻辑的方式。
最近想要整理一下这一年积累的组件化代码,但是没时间写文档。所以我决定按文章连载来写,每补充一个文档,就写一篇文章,并且谈一谈对组件化的理解。
开发比较复杂逻辑的游戏时中可能会遇到一个问题,你要修改代码逻辑要经常在各个脚本文件中乱跳,严重降低了效率,就像缠绕的耳机线,太TM难解了。

如果发生了这样糟糕的事情,那么是时候考虑一下重新组织一下游戏流程的控制逻辑了。有很多方法可以整理代码逻辑,但我们首先容易想到的就是状态机了。
有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
理论难以理解,不如直接实战。
首先,我并不想去实现一个复杂的状态机逻辑,组件化应该保持一定的简洁性。因此该组件并不提供状态的切换条件,所有的切换逻辑都需要开发者自己控制。状态机只提供状态切换,在不同状态调用 进入、离开、刷新的函数,也就是 进入(onXXXEnter)、离开(onXXXExit)、刷新(onXXXUpdate) 这三个函数。
有了这些基本的条件,你可以在任意 状态函数 内,自己写逻辑来进行状态的跳转。为了方便代码编写,需要自定义的FSM脚本直接继承组件使用,这样对应触发的进入(onXXXEnter)、离开(onXXXExit)、刷新(onXXXUpdate)函数就可以直接声明在 新创建的FSM脚本上。
具体用法的代码如下:
const STATE = {
IDLE:“Idle”
WALK:“Walk”,
RUN:“Run”,
STOP:“Stop”
}
@ccclass
export default class MyFSM extends BhvFSM {
static STATE = STATE;
start(){
this.addStates(STATE);
this.changeState(STATE.Idel);
}//可以通过函数参数获得状态名,也可以通过 this.currentState 获得 onIdleEnter(cur:string,pre:string){ this.changeState(STATE.Walk); } onWalkEnter(){ cc.log("开始走路!"); } onWalkUpdate(){ cc.log("走路!"); if(this.duration>=0.5){ this.changeState(STATE.Run); } } onRunEnter(){ cc.log("跑起来了!"); } onRunUpdate(){ cc.log("狂奔!"); //update会持续刷新 if(this.duration>=1.0){ this.changeState(STATE.Stop); } } onRunExit(){ cc.log("不跑了!");}
onStopEnter(){ cc.log("筋疲力尽!"); }}
为了方便快速声明状态函数,vscode 可以在 文件 > 首选项 >用户代码片段,添加这个片段提示。之后输入onFSM 就可以直接补全函数:
"onFSM": {
"scope": "typescript",
"prefix": "onFSM",
"body": [
"on${1:Fsm}Enter(){",
"",
"}",
"on${1:Fsm}Update(){",
"",
"}",
"on${1:Fsm}Exit(){",
"",
"}",
],
"description": ""
},
BhvFSM
功能
简单实现的状态机组件,通过继承方式使用。添加状态后,需要手动维护逻辑。该组件提供基础的状态机功能,会在对应状态变动后触发 进入、更新、离开 三个函数。
使用方法
- 声明 类 MyFSM 继承自 BhvFSM 组件
- 在 start 生命周期函数添加状态名。
- 在MyFSM类中声明不同的状态对应的触发函数: onXXXEnter / onXXXUpdate / onXXExit
- 对应函数会在同名的状态切换的对应时机触发。比如onWalkEnter,是在 Walk 状态进入后触发的。
- 在不同的状态触发函数中,自己控制逻辑操作和对应条件的状态。
- 将 MyFSM 组件 挂在对应的对象身上
PS:注意,状态名 和 状态函数 大小写必须匹配,推荐首字母大写来命名状态名
在线代码和文档
对组件的评价 (满分:5)
实用度:★★★★
复杂度:★
拓展性:★
附带了脚本和例子:
ExampleFSM.zip (4.1 KB)