我正在模仿英雄联盟玩法,遇到一个状态同步问题,小兵和野怪的移动和主动攻击的同步思路应该是怎么样的

怎么不可能?多人即时游戏同步就两个大类, 状态同步和帧同步
帧同步是最精确的同步,服务器只管分发每一帧每个客户端的输入信息,游戏的每个游戏对象,包括自己和敌人以及怪物,不管在不在视野,逻辑都是在自己的客户端每帧全量跑计算的,计算量大,一旦数量多了CPU吃不消,所以你看到的MOBA类游戏,基本都是5V5, 10v10的,并且是单局独立,游戏时间短的,因为你中途加入会从游戏的第1秒开始计算到现在所有的数据

状态同步是能达到最大规模同步的,你所知道的啥百人同屏,千人同屏战斗,都是状态同步,所有的校验都以服务器为主,客户端只管服务器告诉你做什么你就做什么,可以为了效果预先做一些事,但是最终的结果以服务器为准,所有的战斗逻辑AI什么的全都是服务器在跑

你这样都放服务器基本上写不出来,要调试的东西太多了

那这样,先客户端写,把逻辑跟视图分开。
让战斗模块能够单独纯逻辑跑。然后再考虑放到后端上。

先这样吧 我再想想,我先把单机丝滑的做出来

目前的情况是UI和寻路已经弄好了,动画状态机做了一半还在完善

Emmmm,我水平有限,不知道该咋描述。再推荐两篇不错的文章,有空可以研究一下:
《守望先锋》架构设计和网络同步
干货!光子高级工程师揭秘帧同步游戏的技术实现细节

1赞

我记得商城里面有个moba源码可以参考一下

这种并不是标准的状态同步

状态同步确实全部放到服务器计算的,如果想要本地计算,那就走帧同步吧

同步哪有标准。完全可以共用。

确实可以混用,但是使用主流的方案相对来说更好

10人同步完全可以用帧同步, 服务器只需转发客户端移动命令与攻击按钮的下标给所有人包括自己
以前做个类似的,帧同步实现起来比状态同步简单多了
状态同步要考虑的事一大堆,还费服务器资源,浪费钱

目前想到的一个方案就是:

移动:客户端把算出来的路径点传给服务器,客户端先不走,服务器拿到路径点循环分发给所有客户端才去更新位置

释放动作技能:客户端按下技能要经过本地逻辑验证,本地通过后上传给服务器该客户端释放技能的指令,服务器在这1帧,判断这个技能是否符合逻辑(技能够释放距离),如果满足,则再继续等待技能的事件触发(某些技能不是立即生效),当等到事件触发的那1帧,服务器判断并存储这个技能事件影响到哪个客户端英雄,如果有,则分发给所有客户端同步影响到的英雄的状态逻辑

释放魔法范围技能:类似动作技能,英雄联盟的魔法阵伤害累计时间每有1秒则计算1次,比如1个3s的魔法阵0-1-2-3,你站在这上面站了2.5s,则你会吃到2次伤害,只有站满4秒才吃满4次伤害,如果第1次进入,也就是第0s,马上造成1次伤害,接下来开始累加持续时间,对这个累加值进行第1s,第2s,第3s的判断就行。有了这个逻辑,释放技能和释放动作技能类似,服务器确认了你能释放魔法阵之后,服务器不断判断这个魔法阵范围内是否有敌人,如果有,累加这个数值进行伤害的状态同步。

大体上而言
客户端进行大部分战斗逻辑的第1次校验,比如技能是否可以打断平A,平A是否可以打断技能,这点应该是权威的,因为上一次的状态永远是服务器确认之后释放的。

服务器则进行简单的平A范围、技能范围伤害等判定,不需要引入客户端本身的战斗逻辑,服务器只需要告诉客户端你现在应该怎么做。

有问题请批评指正

更正一下,魔法阵那个伤害计算不太对,因为有可能一个英雄进进出出反而受到更多伤害 :upside_down_face:

还有这个同步方式应该不算帧同步吧 :smiley:

补充一些细节,比如我现在正在释放在一个范围内拖拽敌人的技能

现在有1个(正常延迟)的客户端想释放这个技能 和 1个可能会受这个技能影响的(高延迟)的客户端

正常延迟客户端:客户端发送可以释放技能的指令—服务器收到指令确认可以释放—服务器判断当前技能事件触发时影响到的其他客户端分发状态并存储—正常延迟客户端收到指令,在该范围内确实有敌人,播放敌人受拖拽影响的动画(由于正常客户端延迟不大,所以敌人被拖拽的动画近似立即呈现)

受拖拽技能影响的高延迟客户端,由于高延迟,会出现某些情况:
1.我因为同步服务器的移动数据晚,所以我可能并没有走到敌人的技能范围的时候,服务器就已经确认我在这个范围内了,而且我并没有看见对方在释放技能,因为我还没有同步对方的行为
2.正常客户端已经释放完技能了,我是高延迟客户端,我还在进行拖拽动画的播放。

对于这类情况,我想到的是首先在移动指令上做限制,当服务器开始分发所有客户端进行拖拽动画播放的时候,立即屏蔽掉释放这个技能的客户端和受到影响客户端的移动,也就是说,你们2个先别动了,然后在本地客户端的拖拽动画结束之后,本地客户端上传一次我结束拖拽动画的指令,服务器确认了之后,解除该客户端的移动限制。

这样,对于正常的客户端而言,应该是感受不到阻塞感,对于高延迟客户端而言,接收慢上传也慢,高延迟客户端会等拖拽结束后+延迟时间,才能继续接受服务器的同步移动

不知道这点是否正确

貌似学会了一个最基本的平滑公式,比如英雄移速是200。比如寻路完是3条直线,也就是4个点(1个初始点和2个转折点和1个目标点)

服务器60帧1秒计算经过的路径点,每帧经过16.66666ms…,每次计算新坐标后发给客户端同步位置。
公式:每帧新坐标=归一化方向向量(相邻点向量相减) :heavy_multiplication_x: 移动速度 × 0.0166666

客户端比如是120帧,相当于服务器经过了1帧,而客户端经过了2帧,那么服务器在第1帧结束的时候是没有服务器同步的数据,相当于每2帧都会停1帧在原地,理论显示上就是一跳一跳的。

所以直接用服务器同步下来的坐标点,减去当前客户端坐标获得方向向量,然后将方向向量归一化,然后在客户端的FixUpdated里面让 英雄坐标+=归一化方向向量 :heavy_multiplication_x: 移动速度

目的就算让客户端在其余非同步帧时也有坐标变换

小兵的话 我觉得还是状态同步的吧 。

已经解决寻路问题 最新链接 go语言A星寻路初步完成

怎么讲呢,你所有的小兵的行进逻辑不会因为在不同设备有不同表现,除非你代码写的问题,举个例子,纯粹的数学题1+2 = ?的答案不应该在不同国家有不同的结果