是否使用 GKAgents

To use GKAgents or not

我正在开发(或至少尝试开发) 使用 SpriteKit 的相当大的实时战术游戏(类似于 RTS)。

我正在使用 GamePlay 套件进行寻路。

最初我使用 SKActions 在路径内移动精灵,但速度足够快我意识到这是一个大错误。

然后我尝试用GKAgents来实现(这是我现在的状态) 我觉得 GKAgents 非常原始和不成熟,而且它们遵循一些奇怪的牛顿法则 #1,使它们永远移动(我想不出任何有用的场景 - 也许用于 WWDC 的演示)

而且我看到他们有一些 Angular 速度来执行旋转 我根本不需要它,也找不到如何禁用它...

以及 GKBehaviors 给定 GKGoals 似乎做了一些奇怪的事情...

设置避开障碍物的行为让我的单位在他们周围慢跑... 除非 maxPredictionTime 足够低,否则使用 follow path 目标设置行为会完全忽略所有内容...... 我什至都不愿意告诉我把它们结合起来会发生什么。

我觉得很崩溃……

我觉得我现在有两个选择:

1) 与那些代理人进行更多的斗争,并试图让他们按照我的意愿行事

2) 在 GKObstacleGraph 的帮助下自行滚动所有运动和路径查找(这也是越野车,我不得不说在某些点到点的路径将产生最糟糕的路径如 "go touch that obstacle then reverse touch that one then go to the actual point (which from the beginning could be achieved by a straight line)").

问题是:

这些选项中最好的是什么?

获得您所追求的那种行为的最佳方法之一(在 SpriteKit/GameplayKit 中)是识别路径 规划 和路径 following不需要是同一个操作。 GameplayKit 为两者提供了工具——GKObstacleGraph 有利于规划,GKAgent 有利于遵循计划好的路径——当你结合两者的优势时,它们的效果最好。

GKAgent 提供避障功能可能有点误导;请不要将此视为寻找绕过障碍物的路线,更像是对突然出现的障碍物做出反应。)

换句话说,GKObstacleGraphGKAgent就像是用地图导航和安全驾驶汽车之间的区别。前者是您决定选择 CA-85 和 US-101 而不是 I-280 的地方。 (也许偶尔重新评估你的决定——比如,在交通拥堵时选择不同的道路。)后者是你不断地不断改变车道、避开坑洼、超过较慢的车辆、减速的地方对于交通繁忙等


在 Apple 的 DemoBots 示例代码中,他们将其分为两个步骤:

  1. 使用GKObstacleGraph进行高级路径规划。即,当坏人是"here",英雄是"way over there",中间有一些墙,select一系列waypoints,大致近似出一条路线从这里到那里。

  2. 使用 GKAgent 行为让角色大致遵循该路径,同时对其他因素做出反应(比如让坏人不会踩到对方,而是给他们模糊逼真的运动曲线只需遵循 waypoints).

  3. 之间的行

您可以在该示例代码的 TaskBotBehavior.swift 中找到这背后的大部分相关内容 — 从 addGoalsToFollowPath 开始,查看被调用的地方和它发出的调用。


至于 "moving forever" 和 "angular speed" 问题...

agent 模拟是动机类比(即 agent 做需要做的事情以使其在限制条件下"wants")和物理系统(即那些运动被建模为 forces/impulses).如果你拿走代理的目标,它不知道它需要停止——相反,你需要给它一个停止的目标。 (也就是说,移动速度目标为零。)可能有比 Apple 在此处选择的模型更好的模型 — file bugs 如果您对设计改进有建议。

Angular 速度比较棘手。代理的内在物理约束的概念有点类似于陆地上的车辆或海上的船只,这一概念已经很好地融入了系统。它无法真正处理像 space 战士这样的事情,这些战士必须重新调整方向以引导他们的推力,或者可以像向前一样快乐地侧向或向后行走的行走生物——至少,不是靠它自己。您可以通过 maxAcceleration 属性 来改变代理人移动的 "feel",但您受限于 属性 涵盖线性和 angular加速度。

不过请记住,代理系统 "wants" 与游戏世界中的 "actually happens" 之间的接口在您的控制之下。实现 GKAgentDelegate 的最简单方法是仅同步代理的 velocityposition 属性及其代表的精灵。但是,您不必那样做 — 您可以计算出不同的 force/impulse 并将其应用于您的精灵。

我还不能发表评论,所以我 post 作为回答。我最近遇到了同样的问题:agent 在目标周围摆动,或者即使你删除了行为,agent 也会继续移动。然后我意识到行为只是控制运动的算法,但你仍然可以手动访问和设置代理的速度、位置和角度。

在我的例子中,我有一个小动物实体在场景中追逐食物。当它与食品代理接触时,食品实体就会被移除。我尝试了很多方法让小动物在吃完食物后停下来(它会一直直线前进)。我所要做的就是将它的速度设置为 0。那是因为行为不会直接影响位置,而是 speed/angle 组合(据我了解)。当实体没有目标时,它不会 "want" 改变它的状态,所以无论它达到什么速度和方向,它都会保持。它根本不会 update/change 它。所以除非你创建一个目标让它想停下来,否则它会 wiggle/keep 继续。简单的方法是将行为设置为 nil,然后自己将速度设置为 0。

如果behavior/goal系统没有为您要找的动画类型做,您仍然可以使用Agent系统并使用AgenDelegate协议和更新方法自定义动作并制作它稍后与其他代理交互。您甚至可以将代理与通过物理引擎或动作(或任何其他方式)移动的节点同步。

我认为代理系统很好保留,因为您以后可以使用它,即使它仅用于特殊效果。但是就像混合动作和物理会产生一些奇怪的结果一样,混合 goal/behaviors 和任何其他 "automated" 工具可能会导致不稳定的行为。

您还可以将代理系统用于其他用途,而不是四处移动实际的精灵。例如,您可以使用代理充当 "target seeker" 来模拟敌人的反应时间。智能体在场景中移动并寻找其他智能体,当它接触到合适的目标时,敌方实体会攻击它(随机想法)。

这不是 "one size fits all" 解决方案,但它是一个非常好的工具。