- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想使用有限状态机来处理 Entity
我的游戏中的状态。具体来说,就本文而言,我将引用 Player
实体。
我的 Player
将会有空闲、运行、跳跃、下降等状态……并且需要一些方法来管理这些状态以及它们之间的转换。在 OOP 环境中,最简单的解决方案是让每个状态都有自己的类,并有一个名为 handleInput
的方法。接受输入并确定是否应该发生状态更改。例如,在 IdleState
如果 move_right 或 move_left 发生,状态将更改为新的 RunningState
.这很容易也很有意义,因为状态的行为应该封装在状态中。
但是,当您在实体组件系统中使用 FSM 时,一切都会发生变化。状态不再是对象(因为这会违背组件系统的灵 active ),而是组件的不同排列。 JumpState
可能有 JumpComponent
之类的组件, AirbornMovementComponent
等...而 AttackState
可能包含表示攻击的组件,例如 SwingComponent
, DamageComponent
, SwordComponent
等... 这个想法是通过重新排列组件,可以创建新的状态。系统的工作是简单地分别处理这些组件,因为系统不关心状态,它们只关心单个组件。实际的 FSM 位于 FSMComponent
由该实体持有。
这很有意义,除了在处理状态转换时。现在我有一个 InputSystem
查找具有 InputComponent
的实体和 FSMComponent
并尝试根据当前输入更新 FSM 的状态。但是,这并不是那么好用。
FSM 处理输入的最佳方式(在我看来)是让每个状态确定它想要如何处理输入以及如何根据该输入转换到新状态。这又回到了实现 FSM 的 OOP 方式,与 ECS 的设计背道而驰,其中组件只是数据包,系统负责所有逻辑。在 ECS 中,想法是让系统处理状态转换,但这会变得复杂,因为每个 FSM 可能有不同的状态转换条件。
您不能简单地在 InputSystem
中声明“如果输入向右移动,则将状态设置为运行”。这将是特定于玩家的,但可能不适用于 全部 实体。如果有一天我决定让一个敌人变得可控,那么适用于 Player
的输入不会是 Enemy
的相同输入.
我的问题 : 如何让我的 FSM 在 ECS 中足够通用和足够灵活,以允许状态转换的各种实现,而不必在系统本身中进行明确的 if/else 检查?
我是否以完全错误的方式接近这个?如果是这样,在实体组件系统中实现 FSM 的更好解决方案是什么?
最佳答案
只是重复@fallaciousreasoning 的帖子(及其后续评论)。
Ash 实际上有两个在不同级别运行的 FSM。
首先,FSM 在实体级别运行,当您从一种状态转换到另一种状态时,它通过更改实体上组件的组合来管理(实体)状态转换。
其次,FSM 在引擎级别运行,通过更改引擎执行的系统的组成来管理(引擎)状态转换。
它们结合起来形成了一个非常强大的 FSM。
诀窍是确定您需要使用哪种类型的过渡;一种是“数据”组合驱动转换,一种是“逻辑”组合驱动转换。
因此,有了这些新发现的知识,我们就可以推理它是如何工作的。
在更简单的改变组件组成的方法中,我们会使用一些“标记”组件,以及一些冗长的 switch 语句(或 if/else 检查)来处理实体状态的这些变化,最终导致臃肿的系统超过他们应该的。 Ash 的实体 FSM 对此进行了改进,并通过将给定的组件配置映射到标识符并提供可用于触发状态转换的管理器来避免那些冗长的 switch 语句(或 if/else 子句)。此管理器实例可以作为组件内的属性传递,也可以作为系统成员组合/注入(inject)。
或者,采用引擎 FSM 方法,我们将每个特定于状态的逻辑分解到它们自己的系统中,并根据给定的(引擎)状态将它们交换进出。这种方法并非没有缺点,因为缺少系统会影响与其关联的所有实体。但是,将系统专用于单个实体实例(例如,玩家角色)并不少见,因此这在正确的上下文中可以证明是有用的。想想它在某些情况下通过系统交换影响全局实体可能也是可取的。
( 注意:如果您的逻辑修改范围需要更窄,您可以将其限制在系统中而不涉及引擎 FMS。这可以通过在系统中实现状态模式来实现,系统可以通过委托(delegate)来改变其行为到基于状态的不同子系统。)
我已经看到一些 ECS 框架将系统组合标记为“阶段”,但它们从根本上充当 FSM,其中 ECS 引擎使用与给定阶段关联的不同系统集来处理实体。
最后,数据组合只是等式的一半;在尝试在 ECS 中实现 FSM 时,如何组合逻辑位(或 block )同样重要。
关于oop - 实体组件系统中的有限状态机实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39185133/
我有这个代码: System.err.print("number of terms = "); System.out.println(allTerms.size()); System.err
我有以下问题:在操作系统是 Linux 的情况下和在操作系统是 MacOs 的情况下,我必须执行不同的操作。 所以我创建了以下 Ant 脚本目标: /u
我正在调用 system("bash ../tools/bashScript\"This is an argument!\"&"),然后我正在调用 close(socketFD) 直接在 system
使用最初生成的随机元素来约束随机数组的连续元素是否有效。 例如:我想生成一组 10 个 addr、size 对来模拟典型的内存分配例程并具有如下类: class abc; rand bit[5:0
我正在创建一个必须使用system(const char*)函数来完成一些“繁重工作”的应用程序,并且我需要能够为用户提供粗略的进度百分比。例如,如果操作系统正在为您移动文件,它会为您提供一个进度条,
我即将编写一些项目经理、开发人员和业务分析师会使用的标准/指南和模板。目标是更好地理解正在开发或已经开发的解决方案。 其中一部分是提供有关记录解决方案的标准/指南。例如。记录解决/满足业务案例/用户需
在开发使用压缩磁盘索引或磁盘文件的应用程序时,其中部分索引或文件被重复访问(为了论证,让我们说一些类似于 Zipfian 分布的东西),我想知道什么时候足够/更好地依赖操作系统级缓存(例如,Debia
我们编写了一个 powershell 脚本,用于处理来自内部系统的图像并将其发送到另一个系统。现在,业务的另一部分希望加入其中,对数据进行自己的处理,并将其推送到另一个系统。打听了一下,公司周围有几个
我正在尝试朗姆酒我的应用程序,但我收到以下错误:System.Web.HttpUnhandledException:引发了“System.Web.HttpUnhandledException”类型的异
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
所以我在其他程序中没有收到此错误,但我在这个程序中收到了它。 这个程序是一个我没有收到错误的示例。 #include int main() { system("pause"); } // en
我在 c# System.URI.FormatExption 中遇到问题 为了清楚起见,我使用的是 Segseuil 的 Matlab 方法,并且它返回一个图片路径 result。我想为其他用户保存此
我正在尝试像这样设置文本框的背景色: txtCompanyName.BackColor = Drawing.Color.WhiteSmoke; 它不喜欢它,因为它要我在前面添加系统,例如: txtCo
请帮助我解决 System.StackOverflowException我想用 .aspx 将记录写入数据库我使用 4 层架构来实现这一切都正常但是当我编译页面然后它显示要插入数据的字段时,当我将数据
我使用了一些通常由系统调用的API。 因此,我将 android:sharedUserId="android.uid.system" 添加到 manifest.xml, 并使用来自 GIT 的 And
我正在尝试创建一个小型应用程序,它需要对/system 文件夹进行读/写访问(它正在尝试删除一个文件,并创建一个新文件来代替它)。我可以使用 adb 毫无问题地重新挂载该文件夹,如果我这样做,我的应用
我想从没有 su 的系统 priv-app 将/system 重新挂载为 RW。如何以编程方式执行此操作?只会用 Runtime.getruntime().exec() 执行一个 shell 命令吗
我正在尝试制作一个带有登录系统的程序我对此很陌生,但我已经连续工作 8 个小时试图解决这个问题。这是我得到的错误代码 + ServerVersion 'con.ServerVersion' threw
当我“构建并运行”Code::Blocks 中的程序时,它运行得非常好!但是当我从“/bin”文件夹手动运行它时,当它试图用 system() 调用“temp.bat”时,它会重置。这是为什么?它没有
我想使用 system/pipe 命令来执行具有特殊字符的命令。下面是示例代码。通过系统/管道执行命令后,它通过改变特殊字符来改变命令。我很惊讶地看到系统命令正在更改作为命令传递的文本。 run(ch
我是一名优秀的程序员,十分优秀!