首页 > 手机 > 配件 > 魂淡1994的博客,有限状态机

魂淡1994的博客,有限状态机

来源:整理 时间:2022-04-08 08:12:32 编辑:华为40 手机版

能不能通俗的讲解下什么是状态机?

能不能通俗的讲解下什么是状态机

有限状态机:这是个啥?如果你有关注YoYo Games的官方技术博客,也许你曾经见过这篇文章,这篇文章很好的解释了什么事状态机,强烈对此有兴趣的朋友仔细阅读,不过我会先简单定义一下。一个有限状态机(后文以状态机缩写指代)是一种特殊的组织代码的方式,用这种方式你能确保你的对象随时都知道自己所处的状态以及所能做的操作。

其中每一个状态都是独立的代码块,与其他不同的状态分开独立运行,这么做可以使得游戏的调试变得更加方便,同时也更易于增加新的功能(比如一些特殊的能力和动画之类)。玩家角色在跳跃的时候看起来有点奇怪?那就直接去“跳跃”的状态里找问题吧!同样这个机制也可以用于给敌人实现基本的AI逻辑,让敌人可以根据状态做出不同的决策。

恰好状态机机制是本月挑战里的“专家级”难度,但我十分希望当我刚开始学习编程时就能了解这个知识点,正确运用状态机可以为你免去很多不必要的麻烦。接下来我们就来看一下如何使用吧。有限状态机适合我的项目吗?这个问题俨然是“世上没有愚蠢的问题”这句话的最佳反证。状态机系统永远适合你的项目,这个问题可以修改成这样“状态机是否适合我这个对象?”确实,并不是所有的对象都需要用上状态机机制,但你可能会惊讶地发现有那么多对象都适合使用状态机去进行管理。

显然,可控的角色和敌人都需要使用状态机,但实际上我的游戏控制器对象也采用了这一机制,用来区分在主菜单、设置菜单和关卡选择等不同的场景的用途,甚至我的镜头控制器也用了状态机,比方说“跟随玩家状态”,“过场动画状态”和“显示特定对象状态”等等。那么如何才能确认某个对象需要使用状态机呢?其实非常简单,对于每个对象都要问一问自己:“这个对象可以做些什么?”如果这个对象需要处理超过2件事情以上的功能,那你就应该考虑去做一个状态机。

让我们来试着问一下这个问题,比如马里奥,尤其是在超级马里奥世界里,马里奥可以做什么呢?他可以:站立行走/跑躲闪跳爬墙显然上面这个列表还有更多没列出来的,但这是个好的开始。因此,显然马里奥有很多事情可做,而且几乎所有这些事情都是独立的状态,那你现在就已经有了一个对象应该要做的功能列表了,现在是时候画一个流程图了。

认真脸:流程图。不开玩笑,港真,流程图是你的好伙伴。下面是几个示例(从最上面那个链接里借用的)这是上一张图的汉化版?设计好流程图并梳理好你所有需要处理的状态是非常重要的第一步。在你正式开始编码之前,你需要制定出基本的状态和各自的规则。你不需要彻底搞清楚你的角色能做到每一个操作,这是状态机最棒的特性,它总是易于扩展,但是基本的设计是非常重要的。

OK,设计好了。怎么实现呢?最好的办法当然是一头扎进去然后直接动手了,是吧?为了让这个过程变得更轻松简单,我做了一个小脚本可供使用点击前往网盘下载脚本让我们来看一下这个脚本并了解一下它是怎么工作的:state_machine_init()当你在创建需要使用状态机的对象时,可以在Create事件中调用这个脚本。

它会创建一对数据结构和一系列十分有用的变量。现在我们先来看看这些变量state - 这个变量是当前状态的标志位。这个脚本中将会包含在对象step事件中执行的代码。state_next - 当我们切换状态时,我们希望在切换之前当前状态能执行完毕,因此我们调用这个脚本来切换状态,同时更新这个值,然后上述"state"变量将在"End Step"事件中发生变化。

state_name - 这个变量用于获取保存当前状态的名称(创建时设定的名称)state_timer - 这个变量用于记录当前状态持续的“step”数(即运行了多少帧),实用程度绝对超乎想象state_map - 一个ds_map数据结构,把你设定的状态名称作为键名保存进来,state_stack - 一个用来记录你历史状态的数据结构。

可以用来实现一些状态机的进阶功能,比如变回到之前的状态。state_new - 这是个非常有用的变量,当你切换到某个状态时,有可能你希望该状态处于初始化状态,比如速度设为0,或者更新精灵等等,这些情况十分常见。这时候你只需要在状态的最开始将这个值设为“true”即可完成这一切操作。state_var[0] - state_var 这个变量比较特别。

这是一个用来存储某个状态的持续时间的数组。因为我发现我自己经常会有这样的需求——“我想要清楚地跟踪并记录这个状态下的一些信息……但是别的状态没这种需求”那我该怎么办?每次有这种需求的时候都新建一个变量?这不是很荒谬嘛?所以,我用“state_var”来作为替代品,把这个数组作为针对该状态的一个便笺本,或是剪贴板,取决于你的用法。

这个数组可以记录我所需要的值,因此我不必新建变量来进行记录,可能有点说不太清楚,但这个非常有用。如果你下载并仔细看了我提供的脚本,你可能会注意懂我在里面放了一些建议性的变量(也许你的游戏用得着)。比如,通常情况下"state_can_interrupt"或"state_is_invincible" 这些变量都会派得上用场。

文章TAG:

最近更新