RTS游戏中视线计算的快速算法

时间:2010-08-21 10:34:26

标签: algorithm optimization big-o math

我正在制作一个简单的RTS游戏。我希望它能够非常快速地运行,因为它可以与数千个单位和8个玩家一起使用。

一切似乎都完美无缺,但似乎视线计算是一个瓶颈。这很简单:如果一个敌方单位比我单位的任何一个LOS范围更近,它将是可见的。

目前我使用了一种非常天真的算法:对于每个敌方单位,我都会检查我的单位是否有人看到他。它是O(n ^ 2)

所以如果有8个玩家并且每个玩家有3000个单位,那么在最坏的情况下,每个玩家需要3000 * 21000 = 63000000个测试。这很慢。

更多细节:这是一个愚蠢的简单2D空间RTS:没有网格,单位沿着直线移动,没有碰撞,所以他们可以互相移动。因此,即使数百个单位也可以在同一地点。

我想以某种方式加速这个LOS算法。有什么想法吗?

编辑:

所以附加细节:

  • 我的意思是一个玩家甚至可以拥有3000个单位。
  • 我的部队有雷达所以他们朝着所有方向平等。

3 个答案:

答案 0 :(得分:7)

使用spatial data structure有效地按位置查找单位。

此外,如果您只关心一个单位是否可见,而不是哪个单位发现它,您可以

for each unit
    mark the regions this unit sees in your spatial data structure

并且:

isVisible(unit) = isVisible(region(unit))

一个非常简单的空间数据结构是网格:在游戏区域上覆盖粗网格。区域是这个网格的单元格。您分配一个区域数组,并为每个区域保留当前在该区域中的单位列表。

您可能还会发现Muki Haklay's demonstration of spatial indexes有用。

答案 1 :(得分:4)

我用网格做这个。我认为商业RTS游戏是如何解决这个问题的。

  • 为能见度跟踪器推断游戏世界。 (方格是最简单的。尝试粗糙度以查看最有效的值。)
  • 记录每个区域的当前单位。 (每当单位移动时更新。)
  • 记录每位玩家看到的区域。 (这必须在单位移动时更新。单位可以轮询以确定其可见的图块。或者您可以在游戏开始之前分析地图..)
  • 为每个玩家看到的敌方单位制作一个列表(或任何适合的结构)。

现在,当一个单位从一个可见区域移动到另一个区域时,请执行检查:

  • 从看不见的地方出发 - 将该单位添加到玩家的能见度跟踪器中。
  • 从看到的地方看到一个看不见的区域 - 从玩家的能见度跟踪器中移除该单位。
  • 在其他两种情况下,没有发生可见性变化。

这很快但需要一些记忆。但是,使用BitArrays和指针列表时,内存使用量不应该那么糟糕。

在Game Programming Gems的一本书中有一篇关于此的文章(我认为是前三本中的一本)。

答案 2 :(得分:3)

gamedev中最基本的规则之一是通过利用游戏玩法定义的所有可能限制来优化算法中的主体 - 这是您不会在任何给定公司之上构建完全不同的游戏的主要原因游戏引擎,他们如此有效地利用了他们的约束,以至于他们无法处理任何不受这些约束的限制。

那就是说,你说单位是直线移动 - 你说玩家可以有3000个单位 - 即使我假设八个玩家有3000个单位,每个玩家375个单位,所以我认为我可以安全地假设在游戏的每一步(我假设每一步都涉及你上面描述的计算)更多的单位不会改变方向而不是改变方向的单位。

所以,如果这是真的,那么你想把你的所有作品分成两组 - 那些在最后一步改变方向的那些,以及那些没有改变方向的那些。

对于那些做过的人,你需要做一些计算 - 对于任何两个相反力量的单位,你想问'单位A何时会看到单位B给出单位A和单位B都不改变方向或速度? (你可以处理加速/减速,但后来变得更复杂) - 要计算这个,首先需要确定单位A和单位B正在行进的向量是否会相交(简单的2D线交点计算,结合计算告诉你每个单位何时到达这个交叉点) - 如果他们没有,并且他们现在看不到彼此,那么他们永远不会看到对方,除非他们中至少有一个改变方向。如果它们相交,那么你需要计算第一个和第二个单位通过交叉点之间的时间差 - 如果这个距离大于LOS范围,那么除非改变方向,否则这些单位将永远不会看到对方 - 如果这个差异小于LOS范围,那么更多(大力挥手)计算将告诉你何时这个有福的事件将会发生。

现在,你所拥有的是一系列信息,这些信息分成了永远不会看到对方的元素,以及将来某个时间t彼此看到的元素 - 每一步,你只需处理改变了方向的单位并计算他们与其他单位的互动。 (哦,处理以前的计算告诉你的那些单位会相互看到 - 记住将它们保存在一个可插入的有序结构中)你有效地做了什么利用系统的线性行为来改变你的问题'单元A将单元B'看到'当将单元A看到单元B'

现在,所有这些都说,这不是打折空间数据结构的答案 - 这是一个很好的答案 - 但是,它也能够处理随机运动中的单位,所以你想考虑如何优化这个进一步处理 - 你还需要小心处理跨区域的可见性,即两个不同区域的边界处的单位可能能够看到彼此 - 如果你有碎片倾向于聚集,使用具有变量的空间数据结构尺寸可能是答案,其中不在同一区域的碎片保证不能彼此看到。