Minecraft之类的游戏或任何带有拾音器的MMO游戏如何处理它们?
假设您每次挖掘地形时都会产生3滴“污垢”。假设每个项目都有每帧计算的旋转动画。如果全世界的取件数量非常高,那么对于给定服务器中的客户端而言,这将是无用的大量帧开销,因为很可能其中许多取件项距离您仅光年。
所以我认为您只需要在接近本地玩家的拾音器上“做东西”,但这仍然意味着我必须检查每一帧是否有其他拾音器项目足够近以至于必须开始动画。
我的实际问题是:其他MMO如何解决此问题?
Minecraft之类的游戏或任何带有拾音器的MMO游戏如何处理它们?
假设您每次挖掘地形时都会产生3滴“污垢”。假设每个项目都有每帧计算的旋转动画。如果全世界的取件数量非常高,那么对于给定服务器中的客户端而言,这将是无用的大量帧开销,因为很可能其中许多取件项距离您仅光年。
所以我认为您只需要在接近本地玩家的拾音器上“做东西”,但这仍然意味着我必须检查每一帧是否有其他拾音器项目足够近以至于必须开始动画。
我的实际问题是:其他MMO如何解决此问题?
Answers:
只需简单地将世界上那些靠近玩家的部分加载到内存中即可。其他任何东西都被挂在硬盘上。当在两公里外的地方放置一个微小的物体时,玩家将看不到它,也无法与其互动。因此,没有理由对其进行更新或将其发送到GPU进行渲染。对象及其交互范围越小,需要将其加载到播放器周围的范围越小。
关于找出最接近播放器的内容:主要归结为将世界存储在针对空间查找进行了优化的数据结构中。那些很好的候选者是空间哈希和多维树。
您需要管理两个非常不同的事情:
服务器必须以授权方式管理整个世界。为此,必须与N个客户端(其中N为“大量”)进行通信。
从原则上讲,客户可以了解整个世界,但是不需要。对于客户而言,足够了解玩家附近的东西。例如,假设一个相当粗略的网格状分区,则仅需要知道玩家的单元格以及玩家周围的26个单元格(如果您具有2D网格,则需要知道8个单元格)。网格越细越好,但是您可以理解。
现在,很多皮卡是什么?您每秒可能要挖掘5件事,这可能是需要在服务器上更新的二十个数字,并且服务器可能必须将这些数字传输给感兴趣区域与您的小区重叠的其他玩家。对于计算机而言,这是非常荒谬的数据量,而计算量却微不足道。当同一单元中有成千上万的玩家时,这可能会成为挑战(那时您的分区过于粗糙)。
服务器不需要知道,也不必关心拾取器的旋转或此类细节。为什么会这样?
客户实际上也不在乎,因为这只是客户可以即时弥补的眼球。
从服务器的角度来看,有必要知道您正在所在节点中的(30、40、50)处进行挖掘,并且它决定生成例如5个类型为3的对象或7个类型为数3。这就是它所关心的,并且它所传达的所有信息。它还将信息包含在发送给某人的数据中,该人随后将其感兴趣的区域移到网格单元上(假设到那时它仍然在那里)。
客户被告知那里产生了三个物体,等等。现在,无论客户显示的是ASCII艺术图,还是现在有一个“ D”,还是显示旋转的污垢,都一样。桩的旋转角度是否不同,还是仅靠近玩家的旋转角度都相同。只是显示器上显示的内容,不会影响其他任何人。
因此,在您只想旋转附近一堆污垢的具体情况下,您可以对所有已知的对象进行范围检查。由于数据集不大,因此即使对所有内容都使用蛮力也可以使用。
您可以(并且应该)根据分区大小,简单修剪掉距离太远的网格单元。
当然,您可以进一步细分您的单元并使用超级智能的工具。如果可以的话,请使用kd-Tree,但不要期望会有很大的收获。您可以使用Manhattan distace修剪东西,也可以将它们分类为自己的小网格……但是为什么呢?
距离检查(实际上是平方距离,但对您来说是相同的)只是两个乘法和一个加法(已针对MUL,MADD优化,因此实际上只有两个操作),然后是分支或有条件的移动。这几乎与一次不修剪整个网格单元的其他操作一样快。事实上,这是东西,你可能连做在GPU上...
看到您将如何针对同一位置进行几百次或最多几千次的距离检查(平方距离可以很好地工作),那么进行此计算就不会有太多麻烦,甚至更多,因为它是一个相当快的缓存-连续内存上的友好迭代,以及有条件的移动,非常便宜。像(伪代码)之类的东西rot = r[i] + 1; r[i] = ((dx*dx+dy*dy) < DIST_SQ) ? rot : r[i];
。那是对每帧数百个值的数组的一次迭代。计算机对此并不关心,它是连续的加载和存储,简单的ALU,没有分支,只有几千次迭代。
这个问题(多对一)与服务器上的问题(多对多)不是同一类。真的,客户不是问题。
@ T.Sar在评论中写道,您应该查看Minecrafts的“已加载块”概念以获取更多信息。如果这样做了,请注意,由于人们在游戏中建造机器,因此在Minecraft中这相当复杂。
一个非常简化的版本如下:
世界被划分为正方形区域(块)。在Minecraft中也有一个高度划分,但是大多数mmos不需要。
游戏客户端只关心靠近玩家的区域。这比在播放器周围画一个圆要简单得多,但是非常好。
在Minecraft中,区域为16x16块,客户知道大约9x9区域,每个方向上有4个区域。(东边4个区域+区域球员在+西边4个区域= 9个区域。南北相同)
这些数字没有什么神奇的,可以在游戏中使用任何有意义的东西。
客户只会在该区域内制作动画。服务器仅计算诸如在靠近某个玩家的区域中游荡的怪物之类的事情。
当玩家在一个区域内走动时,没有什么特别的事情发生,当他们越过区域边界时,“动画边缘”被推到一个区域上。然后,客户端需要向服务器询问它现在看到的区域。
有几个嵌套的动画限制没有错。例如,有生命的物品掉落在3x3区域中,怪物在5x5区域中徘徊,而景观仅在9x9区域中显示。
服务器保留没有玩家看到的区域的“冻结版本”。如果这需要大量内存,则可能需要一段时间后将其卸载。当玩家下次到达时,将重新加载区域,而物品不会掉落。下次您需要更快一点,播放器1。
minecraft:dirt
)和一个count(30),这样当玩家距离收货足够近时,它会尽可能多地增加玩家的库存。如果玩家仅能容纳6件物品,并且地面上有30个筹码,则玩家将拿起6筹码,地面上的筹码减少到24个