之前做商业小游戏的物理帧同步时,发现使用wasm的物理引擎始终不会同步,但是改为纯 js 的逻辑就同步了,然后花了点时间研究的成果
Demo 信息
小破服务器加载大概10秒左右,请耐心等待
预览地址:http://139.224.226.7:8080/
所有人在同一房间内,可以自行用多台设备对比查看,房间 2 分钟重置一次防止追帧时间过长
- 物理引擎:PhysX
- 开发框架:MKFramework
- 帧同步:包含逻辑/渲染帧管理器,延迟追帧,重连追帧,(未实现预测)
- 服务器:纯 Nodejs 开发,包含简易的房间管理,完整的帧同步逻辑
- 支持平台:Web
- 支持物理引擎:PhysX,Bullet
源码
-
帧同步框架(服务器/客户端):之后会发布在 MK 官网的项目列表
-
物理帧同步源码:之后会发布到商店,可以搜索 3D物理帧同步 查看
同步原理简述
同步依靠Wasm和JS的浮点运算一致性。是否可以同步取决于平台是否符合 ES6 规范,严格来说默认是必须符合的,所以不同步的设备占少数,具体比例未知可自行测试。针对少数不同步的设备解决方案如下
针对少数不同步的处理
客户端将每帧的物理节点坐标及旋转信息生成一个 md5 传递到服务器,如果服务器检测到设备A的 md5 与设备B的 md5 不一致时暂停 A 设备的物理模拟,并通知 B 开始派发坐标,旋转信息到服务器,服务器再转发给设备 A
这样做会导致 A 的延迟增加,但是可以保持一致性,而且 A 属于少数不需要担心服务器资源被占用
仅提供理论,Demo 未包含此逻辑
关于多平台
对于 Android 平台而言,由于物理引擎是C++代码实现的,所以在多设备间仍然可能存在不同步的情况,具体查看 gpt 说明:https://chatgpt.com/share/696ca09c-d53c-8004-93df-b2ab3956e307
按照 gpt 的解释,不同步率也是占据少数,我自己也用一部老手机 魅族MX5(android5.1)和电脑的夜神模拟器(Andorid9.0)测试的情况是同步的。但是原生端目前不支持重置物理引擎(应该可以改C++代码实现),这是物理同步必要的条件。
针对不同步的情况,这里也提出一个想法,检测到不同步后(md5),记录最新的刚体信息,重置多台设备的物理引擎,重新赋值坐标、旋转、速度等… 不过这些都需要后续验证