什么是状态模式
在状态模式中,类的行为是根据状态发生改变的,所以他属于行为模式。当对象中有大量条件分支语句( if语句)和状态变换相关,这时就可以将这些分支语句通过另一种方法实现,例如枚举、继承等
在unity引擎中,直接使用状态模式的组件就是动画系统(虚幻引擎中应该有类似的组件)。动画的播放随着人物的状态的改变而改变,当人物处于行走状态时播放行走动画,跑步状态时播放跑步状态,所以为了直观介绍状态模式,将直接使用动画系统来介绍(反正跟着大佬的理解来,大佬万岁,好吧我大概就复述了一遍)
当你不使用状态模式
当你直接使用条件分支语句控制动画的播放,比如按下空格键播放跳跃动画
if(GetKeyDown(KeyCode.Space)){
//播放跳跃动画
}
如果我再按下空格键会发生啥?跳两次,但是这游戏就是low,只能跳一次那咋办,凉拌。只能判断是否处于跳跃状态
if(GetKeyDown(KeyCode.Space)){
if(isJumping == false){
isJumping = true;
//播放跳跃动画
}
}
如果人物按下左ctrl键就能蹲下,松开又站起来呢?那不简单,判断人物是否按下左ctrl且人物是否在跳跃中播放蹲的动画,松开左ctrl播放站起来的动画不就行了?那问题是,人物他现在多了个蹲的状态,我能否在蹲的过程中直接跳跃(想象一下人物上一帧还蹲着,下一帧直接站立)?那显然不能,我就又得加一个bool变量来判断是否处在蹲的状态了
if(GetKeyDown(KeyCode.Space)){
if(isJumping == false && isDown == false){
isJumping = true;
//播放跳跃动画
}
}
那我又想在加一个攻击状态呢?继续加bool变量!继续加 if 分支!那我。。。加!那我再。。。停停停,代码已经写了一大堆了,每加一个状态都得更改处于其他状态时播放动画的代码,而且代码又混乱量又大,这可不是一件好事(除非你想混代码量,然后迷惑老师,但在实际开发项目中这么写你肯定会被毒打)
这时候你就要注意这个状态模式了
有限状态机
想要使用状态模式,你就绕不开状态机。如果你学过编译原理,或者生物(所以学生物的人咋做游戏来了)那些用到状态机的,你就会对这个东西十分了解。当然,当我放出实际的图你也会恍然大悟
这图够不够明显,还是得来点更熟悉的?
这不是动画状态机嘛,等等,状态机?哦(恍然大悟)。这就是状态机(当然上面那个状态机我没弄完,别干我)。
状态机来源于自动理论,就是离散数学的理论实现。它有以下要点:
- 你拥有状态机是包含所有可能状态的集合。该例中的站立,蹲下,跳跃,跳斩
- 状态机同时只能在一个状态。你人不会既在跳跃状态又在下蹲状态吧,就如同你不能说你自己又在食堂又在教室(某人:我会影分身。我:一边玩去)
- 一连串的输入或事件被发送给状态机。该例中指按下跳跃键,下蹲键,攻击键
- 每个状态都有一系列的转移,每个转移与输入和另一状态相关。箭头就是转移的目标,箭头上标示的就是转移所接受的输入。例如角色正处于站立状态,当按下空格键就进入跳跃状态,再按下攻击键就会进入跳斩状态,但如果开始按下p键,并没有以个箭头上面标识着p键,那该状态不会进行转移
所以状态模式的核心就是———状态,输入,转移
使用枚举
这是一种改善上述情况的方法,将不同的状态存在一个枚举类型中,这是实现状态机最简单的方法
enum State{
STANDING, //站立
JUMPING,