从零开始的MMORPG游戏服务器(16) - Scene Server(12) - 移动误差思考

230 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

本系列代码仓库:Stargazers · dyzdyz010/ex_mmo_cluster (github.com)

今天突发奇想,想看看服务器上玩家角色的位置与客户端差多少。

移动误差

误差,实际上就是在某个时机把 客户端 传来的位置与 服务器 上当前位置进行比较。

误差是客观存在的,因为受延迟等因素影响,相比较的两个坐标并不是严格同一时间的。

对于 延迟 造成的误差来说,客户端将当前时刻的坐标发给服务器,实际上已经经过了一段时间的延迟,服务器在比较的时候是与若干时间之前的坐标相比较,肯定会存在非0的差值。

对于 服务器定时任务 造成的误差来说,由于目前服务器的设置是没 100ms 执行一次,那么如果比较的时刻不是执行的时刻,那么在这 100ms 内就会形成一个时间差,从而造成误差。比如说服务器当前时刻收到一条位移消息,而服务器的运动计算定时任务距离下一次调用还有 10ms,那就是说服务器上当前存储的坐标是 90ms 前的。这时候如果计算客户端与服务器两个坐标的差值,是一定会存在误差的。

误差控制

我们当然是希望客户端与服务端的数据能够完全一致不存在误差,但很可惜这是不可能的。客户端与服务器通信存在延迟,且这个延迟不是完全可控的,即使是网络情况稳定的状态下,延迟的数值也是时刻在发生变化的。即使是 1ms 的变化,也会导致两端的数据出现不同,如果波动更剧烈一点那数据的差异就会显著可见了。

既然误差无法完全消除,那我们就换个思路。虽然误差是由这些不可控因素造成的,但是他们的差值是有限度的。

让我们举个例子。比如假定角色的移动速度是 500/s,那么由 定时任务 造成的误差最大就会是:

5001000100=50\frac{500}{1000} * 100 = 50

即每秒在任意轴向上的误差最大值为 50。这种误差受定时任务的时间间隔影响,间隔时间越长最大误差越大。

延迟 造成的误差,假定延迟为 150ms,那么误差最大就是:

5001000150=75\frac{500}{1000} * 150 = 75

即每秒在任意轴向上的误差最大值为 50。这种误差受延迟时间影响,延迟越大最大误差越大。

我们需要一个最大值就可以,所以我们取两者中较大的一个作为最大容忍误差。假如比较得出的误差超过这个最大值,那就大概率说明客户端存在一些问题,比如作弊。

可视化

我们可以在服务端配套建立一个 Web 服务器,用以在浏览器页面上展示服务器上各个对象坐标的实时变化。

创建一个 Phoenix 框架项目,该框架同样为 Elixir 语言开发,与场景服务器建立连接非常方便,不需要额外的协议,只需要走现成的 BEAM 节点间通信方式即可。

网页后端定时从场景服务器拉取对象列表和他们的坐标,通过 WebSocket 推送给前端。前端利用2D渲染框架对数据进行渲染。这样一来我们对服务器上对象的运动状态也能有一个比较直观的了解。

下一步

下一步我们实现这个 Web 服务器,让服务端的对象数据直观起来。