如何在C#中实现对象的增量压缩?

3
我正在开发一款基于服务器的多人游戏,使用C#编写。 服务器和客户端共享代码,每个对象都有相同的int ID。我希望通过仅发送更改的数据来使网络传输尽量轻便。
游戏中有许多类,它们具有众多字段/属性,经常发生更改。我正在寻求一种检测这些值何时更改并将这些值发送到客户端的方法。
基本上,该算法如下:
1. 标记更改的对象 2. 在网络Tick时与更改后的对象: a. 比较每个属性与其先前状态 b. 仅发送更改的值 c. 存储旧值 3. 在客户端接收它们 4. 实例化相同类型的对象或按ID查找 5. 设置新值
当然,.NET Reflection可能能够解决此问题,但在每个Tick中迭代1000个对象及其属性会对性能造成瓶颈。
我可以发送基本类型(int,float,vector),并保持连接。我的问题是:
- 发送一个对象的Class并实例化它的最佳方法是什么? - 如何检测属性更改,以及如何序列化属性,以便在接收时找到它们的“匹配项”?

3
当然,.NET反射可能能够解决这个问题,但在每一个Tick中遍历1000个对象及其属性会成为性能瓶颈。您已经测试过而不是仅仅假设了吗?这可能不是最有效的方法,但如果对您的需求足够高效,请不要让事情变得复杂化。 - Sean Middleditch
很明显,即使没有任何分析,这也不会起作用。如果有人建议使用ORM和数据库来查找更改,您仍然会建议首先进行分析吗? - Kikaimaru
@SeanMiddleditch:你能给出这类游戏的源链接吗? - Kikaimaru
@Ruzar:“更好”是主观的。除了“更好”之外,请给出一些标准。Reflection对于某些项目来说是最好的选择,因为它(a)完成了所需的工作,(b)不需要额外的开发时间/资金,(c)表现良好。你在做什么样的游戏?你的带宽需求是什么?更新速度需求呢?如果没有使用AOI过滤器,你是否确实每次更新都发送1000个对象?如果是这样,为什么?你的游戏是否是固定设计,还是需要灵活性来继续发展它?没有“最好”,只有“最适合特定用途”。 :) - Sean Middleditch
@SeanMiddleditch:这是一个快节奏的游戏,所以60fps或更高的帧率会很棒。我想要实现增量压缩,就像我在问题中提到的那样。这是我的简单方法:发送的数据包越少越好,更新时间也是如此。不幸的是,我不知道AOI过滤是什么。发送1000个对象是可能的,但不常见(通常更少)。它有固定的设计。我故意没有写最佳。我评论中的“更好”是指反射消耗的CPU时间。如果您知道除了反射之外的解决方案,请随时发布 :) - sabvente
显示剩余4条评论
1个回答

3
你可以创建像这样的东西:
class Mob {
private int _health;
public int Health
{
   get { return _health; }
   set { _health = value; DirtyFlags |= MobDirtyFlags.Health
}
}

这意味着每个属性都需要很多代码。
或者您可以拥有一些自定义字典,该字典中的每个更改都将被跟踪,因此 mob.Properties ["Health"] = 10; 将跟踪您更改了什么。
这就是 Mooege(Diablo 3 模拟器)的做法。
第一种方法可以使用方面进行重写(可能是某些自定义代码,通过 Reflection.Emit 或类似工具在运行时生成上面写的所有代码)。 或者,如果您知道所有实体的外观,可以从某些模板中为它们生成类(使用类似 T4 的工具)
至于序列化,以下内容已经足够好: (键:int,值:object) 其中键将是诸如 ActorProperties { Health,Strength,...} 的一些枚举。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接