【问题标题】:State machine - how to handle outside environment values?状态机 - 如何处理外部环境值?
【发布时间】:2021-07-26 23:17:47
【问题描述】:

我正在开发一个 Unity 中的状态机实现 (c#),计划主要用于 AI 相关的事情。

我不确定我应该如何处理各种“输入”/它应该如何与来自外部环境的知识交互。到目前为止,我考虑并尝试了两种方法:

1,我有一个专门的“查询”类,其中包含各种布尔值。在每个状态的 Tick() 方法结束时,我都会进行一些检查,例如

if (queries.JumpUp) { SetState(JumpState); }

负责切换状态。要更改状态,我只需将 bool 设置为 true。 这似乎工作正常,在“查询”和结果行为之间创建了一个非常松散的关系,并让我将几乎所有的转换逻辑放在一个专用方法中(我的基本 Tick() 方法在其调用 CheckForTransitions() 方法结束,这是我覆盖并放入所有转换逻辑的方法)。 到目前为止它运行良好,但我有点担心这种类型的逻辑可能有点太松散了。

2、为我想要处理的所有可能的“事件”创建虚拟方法。

public override void TryJump() { SetState(JumpState); }

为了改变状态,我显式调用了上面的方法(或一些围绕它的包装,在 StateMachine 中实现)。

这似乎也可以正常工作。与 1 相比,我可以看到一些轻微的负面影响: 我不能再依赖每帧最多进行一次转换这一事实,我也不能依赖这种转换将在帧结束时发生的事实。 我在代码中没有一个好地方可以准确地检查可能发生的排序转换以及它们的条件。 对于每个“TryJump”方法,我必须为每个状态提供大量虚拟方法。这可能是过早的优化(1,我只覆盖“CheckForTransitions()”)。

尽管如此,对 1 中的方法感觉有些不对劲 - 使用这样的布尔值似乎有点奇怪。

【问题讨论】:

  • 这是一个有趣的问题,但可能更适合Software Engineering
  • 我同意,对于 SE 来说更好的问题。通常状态的变化是对动作的响应,而不是通过评估布尔值来触发。
  • 查看github.com/IanMercer/Abodit.StateMachine 了解我如何处理此问题的示例。
  • public override void TryJump() SetState(JumpState) 不是有效的 C#。你的意图是什么?

标签: c# unity3d


【解决方案1】:

我正在开发一个 Unity 中的状态机实现 (c#),计划主要用于 AI 相关的事情。

我不确定我应该如何处理各种“输入”/它应该如何与来自外部环境的知识交互。

状态机适用于简单的 AI 行为,但如果您正在寻找更高级的东西,您最好使用 Utility System / Utility A.I 之类的东西。

它基本上是一个基于分数的系统,AI 会根据得分最高的动作评估它可以采取的行动(可以通过其他方式配置,以及首先要得分的动作)。分数可以基于外部和内部输入,例如 AI 还剩多少弹药或生命值,或者 AI 是否处于追逐玩家(惯性)的中间。与状态机一样,它也可以划分为多个相互影响的级别,例如一个用于反应动作,一个用于目标驱动行为。

对于 Unity,有一个非常好的开源资产,称为 Apex Utility A.I,但它可能有点过时了。但是,如果没有别的,它可以提供一个很好的参考。

Game AI Pro 有很好的article about utility A.I 以及一堆您可能会觉得有趣的其他材料。

为了共享数据,可以使用某种形式的blackboard system

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多