通过.NET套接字同步对象状态

我想实现的是使用套接字同步两个应用程序之间的对象列表的状态。 我所有的尝试,但失败了。

我的方法之一是将每个对象每次更新发送到客户端,这显然是一个带宽问题,我非常局限于我可以发送的对象的数量,因为我发送一个UDP数据包中的所有对象。

我很清楚,我需要将所有游戏对象发送到客户端,然后只更新服务器端更改的字段。 我之所以没有尝试这种方法,是因为我发现了一些障碍。 我的对象被序列化,并希望同步每个属性。

  1. 如何检测属性的更改,而无需在外部实现更改事件,以及inheritance我的主实体类的所有对象。

  2. 对象的属性的每个属性被改变每一帧,所以当我将更改应用到客户代表对象时,它需要很多的处理,因为我需要find每个属性,我需要从对象更改,并为其分配新的价值。

  3. 每个对象都有需要同步的组件。 这些组件在每个游戏对象中包含的列表中。 所以我不仅要简单地同步对象的属性,而且要同时对每个组件的属性进行同步。

  4. 一个属性可以多次改变每一帧,我只想同步帧的最后的属性设置的最后一个值。

我目前不知道如何实现这个方法。 我的第一种方法是有效的,但根据我的理解,这不是最佳方法。 请任何小的暗示或意见可以有助于制定答案。

提前致谢。

对于我所能理解的,我想你可能会考虑制造一个保持帧更新并通过networking发送的singelton工厂。

所以理论上你所做的就是你有一个gameobject,可以称之为GMOBJ。 所以当你在代码的某个地方改变你的属性时,你可以在frameUpdater中注册这个属性。

frameUpdater.RegisterChange(GMOBJ,“scaling”,value);

该string将是该属性的标识符,如果将其放入字典中,您可以轻松地进行多次调用,并且只存储经过编辑的值。 该string也可以是散列码。

在框架的每一端,你会做类似的事情。

frameUpdater.SendChangedData();

然后该函数将构建一个已更改数据的字节数组并将其发送给其他应用程序。

该应用程序会收回它,然后将其反序列化为值并使用propertys更改相应的gameobject。

像这样的事情是我想你想要的。

你几乎肯定不想每一帧更新一切

通常你会把数据分成Atomic事件和连续事件。

所以像位置变化这样的事情将是一个连续的事件,不需要立即处理。 例如,您可以每X毫秒发送一个新位置,客户端可以在旧值和这个新值之间进行插值。

其他事件将是primefaces,例如玩家死亡,因为这需要立即发生,但这些事件通常会比运动animation等连续的更稀疏,也希望轻量级。

你基本上想要客户端猜测所有东西,直到获得服务器响应,在这种情况下,如果猜测错误,它将自己修复为真正的值 – 这是在多人游戏中“跳动”的原因,客户猜测错了,所以玩家被“传送”来匹配真实的服务器价值。 如果延迟很低,而且预测也很好,那么希望这种情况不会发生(或者说不够明显)。 但是,在客户端和服务器之间,通常不需要所有的东西都是完全同步的,只要每隔一段时间结婚一次,就可以节省大部分带宽/性能。

我在这里写了一个关于联网多人游戏的问题的答案: 如何最小化通过现代FPSnetworking发送的数据? 。

总而言之,我们从一个系统开始,读取每个对象上的每个复制字段,并将其发送到客户端。 这很慢,但一旦我们有了这个工作,我们知道我们有一个可靠的基线优化。

我们的下一步是跟踪每一个看起来改变的对象 – 我们基本上在每个领域的setter中放置一个通知,标记整个游戏对象为dirty,并将其放在“dirty object this frame”列表的头部。 只有那些对象才会发送它们的复制字段。 这是一个重大的改进。

接下来,我们实际上在服务器上存储了对象复制字段的“影子副本”。 每次对象被认为是脏的,我们会比较每个领域与以前的阴影值。 如果不同,我们会发送它并将新值复制到卷影副本中。 如果没有不同,我们会跳过它。

最后,我们压缩了一些数据,这样我们就不会把字段作为UInt32发送,比如说,如果值只能在0到7之间。

我希望能给你一些想法。