7

我以前设计过多人游戏,但现在我想创建一个用于学习/挑战目的的 MMORPG 架构。我想在单个服务器上模拟数百(或数千)个并发玩家。

到目前为止一切顺利,除了现在我面临一个问题,即找出一种尽可能快地更新服务器上所有游戏对象的好方法。

我所说的游戏对象是指所有玩家、生物、子弹。

问题是所有玩家、生物、子弹都存储在服务器端内存上的集合中以便更快地处理,并且遍历所有这些以检查碰撞、更新健康、更新移动等……花费的时间太长了.

假设我有 1000 个玩家,全世界有 10000 个小怪,所有玩家和生物都负责创建 5 个其他游戏对象(不多不少),例如子弹。

这将在一个集合中给出 (1000 + 10000) * 5 = 55000 个游戏对象。

在具有 4gb RAM 的双核 HT i5 上迭代所有对象以更新它们需要永远(几分钟)。这是错误的。

迭代时,代码如下所示(伪):

for(int i = 0; i < gameobjects.Count; i++) {
  for(int j = 0; j < gameobjects.Count; j++) {
      // logic to verify if gameobjects[i] is in range of
      // gameobjects[j]
  }
}

作为一种优化,我正在考虑将我的游戏对象划分为不同的区域和集合,但这并不能解决我需要每秒更新所有对象多次的问题。

我应该如何继续更新服务器端的所有游戏对象?我进行了大量搜索以找到有趣的游戏设计模式,但到目前为止还没有结果。:(

提前致谢!

4

3 回答 3

4

我会完全改变设计并实现一个事件库设计。这有很多优点,显而易见的一个是您只需要更新实际正在与之交互的对象。因为您将始终让 MMO 游戏中的大多数游戏对象处于空闲状态,或者根本看不到。

没有理由计算在任何玩家屏幕上不可见的对象。那将是疯狂的,并且需要您很可能负担不起的服务器场。相反,您可以尝试预测运动。或者存储当前未与之交互的所有对象的列表,并不太频繁地更新这些对象。

如果玩家看不到物体,您可以远距离传送该单位,而不是让它平稳移动。本质上是在允许物体移动的有限区域内将单元移动到很远的距离。即使对象对玩家不可见,也让它看起来像是在自由移动。通常这会在新玩家进入或离开区域时作为事件触发。

您可以通过简单地计算自上次更新以来的时间并预测对象将行进多远来实现这一点,就好像它对玩家可见一样。这对于具有设定路线的对象或 NPC 尤其有用,因为它使计算更加简单。

于 2013-04-28T15:19:03.170 回答
2

您的代码运行如此缓慢,不仅是因为它检查了所有 N 个对象,还因为它检查了所有可能的对象交互,并且在您的示例中需要 N^2 计算 = 3 025 000 000。

减少这种检查次数的一种方法是将游戏世界中的对象放入网格中,以便不在相同或对齐单元格中的对象无法相互交互。

此外,您当前的代码会检查每个交互两次,您可以通过在内部循环中从 i 开始循环来轻松解决此问题:

for(int i = 0; i < gameobjects.Count; i++) 
  for(int j = i; j < gameobjects.Count; j++) 
于 2013-04-28T15:13:51.503 回答
0

循环超过 55,000 个对象应该不会太慢。显然,您在这些对象上做的事情太多,而且可能做一些不应该总是做的事情。

例如,如果一个小怪周围没有玩家,真的应该计算吗?(如果一棵树倒在森林里,周围没有人,它真的会发出声音吗?)

此外,很多对象可能不需要在每个循环中更新。例如,玩家可以留给客户端计算,并且每 1-2 秒只“验证”一次。将所有玩家的冲突转储到客户端将使您的服务器工作负载更容易处理。玩家的子弹或光线投射也是如此。作为回报,它也使游戏对玩家来说更加流畅。

跟随路径时的生物是否需要进行碰撞测试,或者路径的节点是否足够?

将每个对象与其他对象进行测试是很糟糕的。是否所有生物都必须与所有其他生物进行测试,还是只需要测试特定类型或派系?你能把你的世界分成更小的区域,只测试里面的生物和里面的物体吗?

MMO 服务器的代码需要做大量工作才能使其正常工作。所做的优化有时是疯狂的,但只要它有效。

于 2013-04-28T15:11:10.317 回答