我正在开发一个游戏引擎,它是从Quake 2松散衍生而来的,添加了一些诸如脚本效果之类的东西(允许服务器向客户端详细指定特殊效果,而不是只有客户端能够使用的有限数量的硬编码效果) )这是网络效率与灵活性的权衡。

我遇到了一个有趣的障碍。请注意,最大数据包大小为 2800 字节,每个客户端每帧只能发送一个数据包。

这是执行“火花”效果的脚本(可能适用于子弹撞击火花、电击等)http://pastebin.com/m7acdf519 (如果你看不懂,别担心;这是我制作的自定义语法,与我提出的问题无关。)

我已尽一切可能缩小该脚本的大小。我什至将变量名称简化为单个字母。但结果正好是 405 字节。这意味着每帧最多可以容纳 6 个。我还想到了一些服务器端的更改,可以将其再减少 12 个,而协议更改则可能会再减少 6 个。尽管节省的费用会根据您使用的脚本而有所不同。

然而,在这 387 个字节中,我估计在效果的多次使用之间只有 41 个字节是唯一的。换句话说,这是压缩的主要候选者。

碰巧的是,R1Q2(具有扩展网络协议的向后兼容的 Quake 2 引擎)具有 Zlib 压缩代码。我可以引用这段代码,或者至少严格遵循它作为参考。

但 Zlib 一定是最好的选择吗?我至少可以想到一种替代方案,LZMA,而且很容易有更多。

要求:

  1. 必须非常快(如果每秒运行超过 100 次,对性能的影响必须非常小。)
  2. 必须将尽可能多的数据塞进 2800 字节
  3. 元数据占用空间小
  4. 兼容GPL

Zlib 看起来不错,但是还有更好的吗?请记住,这些代码还没有被合并,因此有足够的实验空间。

谢谢 - 麦克斯

编辑:感谢那些建议将脚本编译为字节码的人。我应该说清楚——是的,我正在这样做。如果您愿意,可以在我的网站上浏览相关源代码,尽管它还没有“美化”。
这是服务器端代码:
卢阿组件: http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/lua/scriptedfx.lua
C成分: http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/game/g_scriptedfx.c
对于我发布的特定示例脚本,这会将 1172 字节源减少到 405 字节——仍然不够小。(请记住,我希望将尽可能多的内容放入 2800 字节中!)

编辑2:无法保证任何给定的数据包都会到达。每个数据包都应该包含“世界状态”,而不依赖于先前数据包中传达的信息。通常,这些脚本将用于交流“眼睛糖果”。如果没有一个空间,它会从包装中掉下来,这没什么大不了的。但如果掉落的东西太多,事情在视觉上就会看起来很奇怪,这是不希望的。

有帮助吗?

解决方案 2

最终更新: 这两个库看起来差不多。Zlib 的压缩率提高了大约 20%,而 LZO 的解码速度大约快两倍,但两者的性能影响都非常小,几乎可以忽略不计。这就是我的最终答案。感谢所有其他答案和评论!

更新: 在实施 LZO 压缩并看到性能明显改善之后,很明显,我自己的代码对性能影响负有责任(每个数据包可能的脚本效果数量大幅增加,因此我的效果“解释器”得到了更多的运用。)对于急于推卸责任的行为,我深表歉意,希望大家不要感到难过。我会做一些分析,然后也许我能够得到一些对其他人更有用的数字。

原帖:

好吧,我终于开始为此编写一些代码了。我从 Zlib 开始,这是我的第一个发现。

Zlib的压缩是 疯狂地 伟大的。即使使用 Z_BEST_SPEED(而不是 Z_DEFAULT_COMPRESSION)进行压缩,它也能可靠地将 8.5 kib 的数据包减少到 750 字节或更少。压缩时间也相当不错。

不过我不知道解压速度是多少 任何事物 甚至可能会这么糟糕。我没有实际数字,但每个数据包至少需要 1/8 秒!(Core2Duo T550 @ 1.83 Ghz。)完全不可接受。

据我所知,LZMA 是性能较差与性能较差之间的权衡。与 Zlib 相比,压缩效果更好。由于 Zlib 的压缩已经过大,而且性能也已经非常糟糕,LZMA 目前已经不被人们所关注。

如果LZO的减压时间像它声称的那样好,那么我就会使用它。我认为最终服务器在极端情况下仍然能够发送 Zlib 数据包,但客户端可以配置为忽略它们,这将是默认设置。

其他提示

利兹奥 可能是一个很好的候选人。

兹库 可能是一个很好的候选者 - 许可证非常好,运行速度快,其作者表示它的开销非常小,而开销正是使用少量数据时出现问题的原因。

你应该看看 开放式TNL 并调整他们在那里使用的一些技术,例如网络字符串的概念

我倾向于使用每个字符的最高有效位,这目前被浪费了,通过向左移动 9 个字节的组,您将适合 8 个字节。

您可以更进一步,将字符映射到一个小空间中 - 您可以将它们减少到 6 位(即)仅具有 64 个有效字符),例如,不允许大写字母并从每个字符中减去 0x20 (以便空格变为值 0 )

您可以进一步映射每个字符的频率并进行霍夫曼类型压缩以减少每个字符的平均位数。

我怀疑没有任何算法可以比一般情况下更好地保存数据,因为在您已经进行的更改之后,消息中基本上没有冗余。

发送脚本的二进制表示怎么样?

所以我正在考虑抽象语法树的行,每个过程都有一个标识符。

这意味着由于一次性解析而提高了客户端的性能,并且由于删除方法名称而减小了大小。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top