在Unity中使用有限状态机
有什么不明白的地方,扫描右方二维码加我微信交流。
做了有5年游戏了,有限状态机也很早就听说过了,但一直没使用过,参与的项目里也没使用过。
今天在掘金上看到一篇博客(点击查看),看完有所悟,有限状态机也不是很难嘛。下面讲一下我学到的有限状态机。
概念
有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机(英语:finite-state automation,缩写:FSA),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型。
如上图所示:opened和closed状态切换。
简单举个例子
灯有开和关两种状态,并且两种状态之前可以相互转换。
现在小明刚回到家,灯是关闭状态,小明打开开关,灯通电,变亮,转换为开启状态。
与图中的状态对应起来就是:
entry action:灯是关闭状态。
transition condition:灯开启的条件,即灯当前是关闭状态且打开开关。
transition:灯通电,变亮。
state opened:转换为开启状态。
关灯亦是如此。
再举个游戏中的例子
跑酷游戏主角,在游戏中有3个状态,跑动状态,一段跳状态,二段跳状态。3个状态,满打满算,可以有6种转换组合,但不是每种组合都符合实际情况,状态转换关系如下:
跑动 => 一段跳;
一段跳 => 二段跳;
一段跳 => 跑动;
二段跳 => 跑动;
不符合实际情况的状态转换:跑动 => 二段跳,二段跳 => 一段跳。
状态的切换依赖于当前状态和输入条件。
关系转换图如下:
下面上一个简单的跑酷Demo(Demo仓库地址)
假设篮球为角色,角色有3个状态,如下:
跑动状态:在地面向右滚动;
一段跳状态:停止向右滚动,颜色变红,并跃起到空中;
二段跳状态:停止向右滚动,颜色变蓝,并跃起到空中。
状态转换关系上面已经介绍过了。
Demo中的状态机类:FSM,这里不再过多介绍源码,只是把参考博客里的代码做了一些改动。
下面介绍使用方法:
//定义3种状态 public class PlayerState { public const string Run = "Run"; public const string Jump = "Jump"; public const string DoubleJump = "DoubleJump"; }
private void Start() { //给角色的状态机添加3种状态 _playerState.AddState(PlayerState.Run); _playerState.AddState(PlayerState.Jump); _playerState.AddState(PlayerState.DoubleJump); //添加状态转换,从Run到Jump _playerState.AddTranslateState(PlayerEvent.EVENT_JUMP, PlayerState.Run, PlayerState.Jump, o => { Jump(); }); //添加状态转换,从Jump到DoubleJump _playerState.AddTranslateState(PlayerEvent.EVENT_JUMP, PlayerState.Jump, PlayerState.DoubleJump, o => { DoubleJump(); }); //添加状态转换,从Jump到Run _playerState.AddTranslateState(PlayerEvent.EVENT_RUN, PlayerState.Jump, PlayerState.Run, o => { Run(); }); //添加状态转换,从DoubleJump到Run _playerState.AddTranslateState(PlayerEvent.EVENT_RUN, PlayerState.DoubleJump, PlayerState.Run, o => { Run(); }); //Demo中的篮球开始是从空中掉下来的,我们就假设它的初始状态为Jump _playerState.StartState(PlayerState.Jump); State = _playerState; }
运行Demo,按空格篮球跳跃,如下图所示:
当篮球从空中落地时,顺时针旋转,当前为Run状态;
按下空格键,篮球跳起,变红,停止旋转;
再次按下空格键,篮球再次跳起,变蓝,依然停止旋转;
篮球从空中落地,篮球变回正常颜色,向右旋转。