Answers:
我将通过高层讨论来解决这个问题,然后解决您的问题。为了公开起见,我没有个人使用socket.io的经验,但是有很多关于MMORPG的问题空间。
MMORPG引擎网络架构的设计和/或选择提供功能的中间件或开源项目是受团队的游戏设计,预算和技术专长影响的更具挑战性的决定之一。最终选择将影响其他体系结构决策(有时还会影响设计决策)。
作为MMORPG的开发人员,我们计划取得巨大成功(通常也称为灾难性成功),在这种情况下,大量的警告灯和警报器会触发。出现的可怕的大量数字之一是N平方的算法(此后为N ^ 2),在您的问题中,我首先想到的是,听起来像是设计要求实体将信息广播到所有其他关联实体。这是N ^ 2问题的经典示例。
MMO通常通过以几种不同的方式攻击N ^ 2问题来解决该问题。意识系统(情境,空间等),其中一个实体了解所有其他实体的某些子集,将玩家划分为不同的“碎片”,将玩家划分为“区域”和/或实例化,实施阻止太多游戏的游戏机制玩家聚集在一起(Asheron Call的传送风暴)等
大多数MMORPG和许多FPS引擎都具有相当复杂的网络体系结构,支持各种功能,包括:
我发现虚幻网络文档和Valve网络文档为各种问题提供了很好的入门。
因此,现在让我们解决问题。
例如,每1/10秒一次“收集”并广播它们是一个更好的主意吗?
很难在这里提供简单的是或否答案...因为它取决于规模(观察实体的数量),更新的频率和更新的大小。例如,如果更新的大小可能会在某个地方占用缓冲区,则将它们全部收集可能是非常错误的。
MMORPG和FPS游戏的客户端通常经过设计,即使它们没有收到比“正常”更多的更新帧的更新,它们也将可视化“看起来”正确的内容。当使用不可靠的通信(UDP)时,您可能会期望在虚空中丢失一些更新,客户端可以通过发送比可靠传输更频繁的更新来弥补这一点。
从对socket.io文档的粗略回顾来看,它似乎同时支持可靠和不可靠的(在术语上是易变的)通信路径。
我首先要解决,需要多久更新一次...
如果播放器以恒定的速率直线移动,则较低的更新频率就可以了,因为观察者可以准确地预测播放器在任何时间点的位置。当玩家转弯或快速改变方向时,则需要更频繁的更新。相反,当玩家根本不移动时,根本没有理由发出移动更新。
无论如何,可能(通常)没有必要将每个帧的更新从客户端发送到服务器。服务器本身可以选择在拥有消息的每个帧中发送消息,或延迟消息(请参阅带宽整形,优先级划分和更新生存期)。
其他类型的更新具有不同的特征...例如,当玩家或生物受到损坏时,将修改“健康”字段。一种实现此方法的方法是在发生更改时立即广播每个更改,但是如果在一个帧或连续的帧中多次更改该值,则会浪费处理和带宽(实现带宽整形的网络体系结构通过将更新合并为当它们具有可用带宽时,仅将最新消息发送给观察客户端。
客户应该在出现后立即发送许多不同的消息(获得的经验值,单击的项目)还是仅收集一条消息?
同样,这里没有简单的是或否答案。取决于您所说的收集的确切含义……两者在不同情况下可能都是正确的,并且还取决于网络层的实现。
相反,为特定实体收集一条消息作为一条消息来发送消息(取决于实现)可以反过来减少发送消息的带宽开销(降低成本)(取决于实现,例如通过字符串传达的字段/值映射)可以增加带宽要求与较简单的特定消息类型相比。
回顾socket.io文档,在我看来,消息开销在频谱的高端,这将有利于收集更新以聚合消息的形式发送,而不是大量的单个更新。
我建议您查看所有您打算复制的更新,例如,大多数MMORPG和FPS都不会费心将玩家点击X事件发送给观察客户端,除非这也会导致他们也意识到其对象的状态更改。
一种工作方式是将实际数据更改与这些更改的广播分离。当对象发生更改时,请进行修改并设置一个“脏”标志,当需要广播任何更改时,仅发送已标记对象的数据并清除该标志。多次更改的值将在此处自动合并,因为您的更新仅在广播时发送状态。您还可以标记子对象或单个属性,以便仅广播已更改的内容。
哦,通常您不会将动画帧发送到服务器或其他客户端。精确的动画状态通常被视为演示文稿的详细信息,并留给每个客户端来解决,而您只需要确保每个客户端都知道当前正在播放哪个动画即可。