状态机 有限 (状态机三种表示方法)
本文目录导航:
- (有限)状态机
- [因为我不懂啊]-什么是状态机编程(设计模式)(3)
- [玩转UE4/UE5动画系统>设计篇>动画状态机设计模式] 之 洋葱模式(Onion Pattern)
- 动画状态机设计模式:洋葱模式简介
(有限)状态机
状态机是最基本的设计模式。

而我们常常说的状态机指有限状态机,缩写是FSM(Finite State Machine)。
无限状态机仅仅是理论上存在的概念,比如,把1/3变成一个状态机的话,那这个状态就是无限循环了,实际上没啥实际的应用意义。
我们常说的状态机指有限状态机。
不夸张的说,状态机模型是世界运行的基础,大脑做的决策推演,在火星上运行的祝融号,计算机软件的底层设计,游戏中的沙雕AI,其底层逻辑都是状态机。
有限状态机的定义: 有限个状态 及在这些状态之间的转移和动作等行为的数学模型;在计算机科学中,状态机的关键要素是状态和状态的转移。
按照输入输出关系,状态机模型有2个,分别是Moore模型(发明者:Edward Moore 1956)和Mealy模型(发明者:George H. Mealy 1955),看到这俩名字,莫名的就想到了《Rick and Morty》...
这两个模型的特点可以用如下公式概括:
一句话:
Moore的设计仅仅与状态有关,Mealy的设计与状态和输入有关系。
Mealy的状态比Moore的状态要少。
它们的设计和表示方法如下所示:
moore和mealy本质上并没有什么差别,设计上可以互相转化。
上图中的A Mealy 转为 Morre 如下所示:
上图中的B Moore 转为 Mealy 如下所示:
推导过程可以参考:回到程序设计的话题,要设计一个通用的状态机程序,只用switch,case肯定是不够的;
当然,不管是用哪种语言,只要把握住状态机的三个核心要素即可,即:
画成一张图如下(手动 @陈振):
把它转换成一个数据结构,即:
通用的设计思路是把所有的状态和状态转换表达成一个表,通过查表的形式驱动状态机运转起来。
状态转移表,示例是一个输入4个数字密码(9527)的状态转移表:
状态机的查询和运转:
运行结果展示:
在python里面有一个transitions状态机库,感兴趣的同学可以自己学习一把。
运行结果:
掌握了核心思想,设计一个状态机的通用程序并不是很复杂的事情。
[因为我不懂啊]-什么是状态机编程(设计模式)(3)
上一篇文章写完之后,我一直在想做一个游戏示例,想将之前学到的状态机模式运用在其中。
然而一直遇到各种奇怪的bug(之后写出来),所以一直没有完成这件事。
而且加之自己又犯懒了,所以我决定做一件更简单的事,以更容易接近的目标来引诱懒的不行的自己。
废话说完,来说正经事了。
前几天认真看了一篇 博客-游戏状态机(侵立删),觉得挺不错的,建议盆友们认真看一看。
读完博客之后,之前计划的示例貌似有了头绪,(废话型)总结出来,实现一个游戏状态机结构需要进行如下几步:
我要做一个简单的UI切换示例,所以简述需求就是: 打开程序进入主界面,主界面中点击开始游戏,进入游戏界面,游戏界面中点击结束游戏,进入结算界面,结算界面可以点击回到主界面,进入主界面,也可以点击重新开始游戏,再次进入游戏界面。
从需求描述来看,状态有三个:
事件有四个:
然后(装模作样的)画了一个状态转换表:
之前一篇文章中有提到过的,在Cocos2d-x游戏开发中,刚好使用Scene来作为控制器,由Scene来控制各层的出现和消失。
这里贴出Scene的源码(完整的源文件,包括了后续步骤才会出现的状态基类,以及派生的状态类):
上面可以看到,Scene中主要包含了:
包含了以上内容,本示例中的这个Scene就能起到控制器的作用了。
状态基类是很有必要的,为了达到各个同级状态都能通过同一个控制器来进行状态转换的目标,各个状态类进行切换时必须有一套统一的流程。 这里贴出本示例中状态基类的源码:
这个源文件中包含了:
所有的派生状态类都会 include 这个文件,实现虚基类 GameTwoState 中的方法,所以所有的状态类都有统一的切换流程:
而且在完成某个事件,需要进行状态转换时,可以通过发送自定义事件来完成消息的传递,自定义事件名放在这里也是为了方便起见。
这里直接贴出几个State的源码了,其中包含注释,废话就不重复再写了:
到这里,上面所提到的步骤全部进行完了。
这个UI切换的状态机示例也就完成了。
在中,直接进入Scene中:
进入主界面 :
此时的Log:
点击Start,进入游戏界面 :
此时的Log:
<Exit>->MainLayer <Enter>->GameLayer <Execute> ->GameLayer
点击Over,进入结算界面 :
此时的Log:
<Enter>->GameLayer <Execute> ->GameLayer [Event]->Game_Over <Exit>->GameLayer
<Enter>->ResultLayer <Execute> ->ResultLayer
点击Replay,重新进入游戏界面 : 此时的Log:
<Enter>->GameLayer <Execute> ->GameLayer [Event]->Game_Over <Exit>->GameLayer
<Enter>->ResultLayer <Execute> ->ResultLayer [Event]->Result_Replay <Exit>->ResultLayer
<Enter>->GameLayer <Execute> ->GameLayer
点击Over,再次进入结算界面,然后在结算界面点击Home,回到主界面 上面的两次操作完成后,Log如下:
<Enter>->GameLayer <Execute> ->GameLayer [Event]->Game_Over <Exit>->GameLayer
<Enter>->ResultLayer <Execute> ->ResultLayer [Event]->Result_Replay <Exit>->ResultLayer
<Enter>->GameLayer <Execute> ->GameLayer [Event]->Game_Over <Exit>->GameLayer
<Enter>->ResultLayer <Execute> ->ResultLayer [Event]->Result_Home <Exit>->ResultLayer
<Enter>->MainLayer <Execute> ->MainLayer
这里用FSM实现UI切换示例只是众多方法中的一种,暂时还没有去比较它们的优劣。(使用markdown编辑器的经验值+1)
可能性多种多样,如果有小伙伴比较过这些方法。
求留言告知,求分享经验。
[玩转UE4/UE5动画系统>设计篇>动画状态机设计模式] 之 洋葱模式(Onion Pattern)
本文档是《玩转UE4/UE5动画系统》系列教程的一部分,由作者老王在知乎和CSDN的专栏同步发布。
教程内容将通过开源项目形式存放在GitHub:玩转UE4(GitHub),所有资源和工程文件均可供免费查阅和下载。
动画状态机设计模式:洋葱模式简介
作为虚幻引擎动画系统学习实践的一部分,我分享了动画状态机设计模式中的洋葱模式概念。
虽然并非严格意义上的软件设计模式,但用于理解和组织复杂动画状态机逻辑,有助于降低复杂度并促进代码复用。
值得注意的是,目前虚幻引擎动画模块的特性限制了对其设计模式的总结,但随着引擎的发展,这个领域仍有待丰富和完善。
以advanced locomotion system v4中的八方位地面运动为例,我们首先实现基础状态机,包含八个方向的走/跑混合,命名为8-direction Movement : Base,并存储其姿态。
接着,创建细节状态机8-direction Movement : Gait Detail,添加步态细节,如Normal、Excited和Tired状态,每个状态内部包含基础状态机,并通过Gait标志位控制状态切换。
洋葱模式是动画状态机设计模式的一种尝试,虽然目前尚不完善,但它提供了一种组织和理解复杂动画逻辑的有效框架。
希望这个分享能启发大家在虚幻引擎的动画设计中找到适合自己的方法。
持续关注,期待虚幻引擎动画模块的进一步发展和动画设计模式的深化。