小飞机工作笔记(一)方案简述

    今天主要就是在继续核心战斗的开发。游戏的玩法很传统,就是带一队英雄在2D横版副本上,可以划线拖动,以及释放技能刷怪。对战我希望可以做成多人实时的,但由于涉及到玩家的操作,想要做到很平滑的体验,状态同步加简单的渲染层预测依然是不够的。多人实时对战的,之前用unity做手游时,探索过帧同步+ECS+渲染层预测回滚的解决方案。但是帧同步对于小团队开发太耗心力了,其它的不说,光是辅助的调试工具以及大规模的测试都是小团队难以胜任的,更何况是采用Js的H5呢。不过我还是使用Js实现过一个帧同步的版本,因为开发H5才又去学习的Js,然后开发过程发现Js的number数据类型无法区分整型和浮点,虽然说动态语言似乎都是不区分整型和浮点的,但是像Lua这种我还可以嵌入C模块,可Js要跑在浏览器里面,目前就我的了解,是无法嵌入C模块的。这样就使得定点数的实现非常困难。后来还是找了个BigInteger.js,内部直接用字符数组来模拟整数运算的去实现定点数运算,但是性能堪忧。
    因为这个原因,同步方案成了我的一块心病,有一天突然想到,其实状态同步也是可以和ECS、状态回滚很好地结合在一起的。轻io竞技的这种,参与的玩家一般是3V3或是5V5左右,而玩法一般也不会太复杂,地图上不会像RTS或是MOBA那种出现大量的作战单位,因此相较于帧同步,需要同步的数据量并不会多多少。核心的逻辑依然独立出来,每帧计算出单独的数据副本,渲染层轮循核心逻辑层作插值展现。服务器的话,也同时跑同样一套核心逻辑,在检测到不同帧的状态数据有改变时,则将改变的数据按帧同步到客户端即可。如果客户端的演算超前于同步状态帧的话,则只需要以服务器的状态帧为准,重置先前的逻辑帧,并且从重置帧重新向后演算即可。渲染层因为是插值演算,在网络抖动不是很大的情况下,重置后依然可以保持平滑的体验。由于是以服务器状态为准,两边客户端的本地演算出现偏差也没有关系,而且一些关键的数据(比如玩家或怪物死亡等)必然会被检测到并同步到客户端,因此即使客户端演算与服务端演算出现偏差,出现服务器认为没有变动而客户端演算认为变动的数据,导致画面的展现与服务器状态不是完全一致,也不会对用户体验造成多大的影响。更何况这种不一致本来就是小概率事件。
    对于数据变动的检测,在服务端,只需要每帧之间对所有entities的components做一个对比,搜集变动的数据并打包下发到客户端即可。当然,这也是归功于ECS(Entity-Component-System)的设计思路,不仅使得数据与行为完全分离,中间状态的计算与回滚成为可能,也使得能够摆脱类型的束缚,以一种统一的方式来处理对象各属性的数据。

posted on 2018-07-23 09:36  莫行  阅读(530)  评论(0编辑  收藏  举报

导航