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

比如说5V5,10个客户端都有小兵野怪,小兵遵循寻路插件,那么这些小兵的同步是以单个客户端为准,还是服务器检测呢,如果是服务器检测逻辑会不会变得很复杂,因为小兵会与小兵互殴

比如在大龙攻击范围,采用服务器检测的话,假设有2个客户端A和B即将进入大龙自动攻击范围
假设:A延迟高 B延迟低

如果野怪采用服务器检测,那么就算A和B同时到达大龙攻击范围,由于A延迟高,服务器接收到A的同步请求晚,所以服务器先判定B进行大龙自动攻击范围。

如果小兵采用服务器检测,首先小兵每隔一段时间服务器下发命令给客户端生成小兵,小兵在制作的时候3条分路已经设置了中间点和终点目标(因为寻路插件,上下路要设置中间点防止跑到中路)

我的疑问就是如何对小兵状态同步尽可能满足所有人

1赞

状态同步的话,所有操作全放服务端就行了,客户端发送操作指令,以及接收消息更新游戏

1赞

英雄联盟目前用的是状态同步

关键是小兵的同步思路如何做

就和上面那位同学说的那样,整个战斗逻辑都在后端跑。
客户端接收后端下发的消息,更新游戏就好

怎么可能整个战斗逻辑都在后端跑,状态同步是后端确认指令确认状态再分发给所有人,延迟等于客户端->服务器处理->客户端,延迟相当于客户端来回+服务器处理时间

对于英雄而言,我点击地板,移动的延迟是我发送服务器的延迟加上服务器确认指令分发下来的延迟。
我先不动,当服务器确认了这个移动的指令然后分发给所有人我才移动,而且我的移动是根据本地寻路插件计算的,我只需要上传我当前的位置给服务器,服务器再分发给所有人

对于技能而言,本地先确认当前能不能释放技能,如果能释放,那么将该指令上传给服务器,服务器分发给所有人,我才能释放技能

对于群体控制技能,我暂时的思路是服务器接收到某个客户端想释放控制技能的那一刻开始计算触发时间,因为控制技能是技能某个中间段生成一个东西能够产生某些影响。
所以这个时间 = 释放该技能的客户端到服务器的延迟时间 + 技能开始到中间段产生事件的时间,当这个触发时间来到的那一刻,服务器判断这个事件范围坐标内有没有某个客户端的被影响了,如果有,则将影响的客户端分发给所有人。注意:服务器接到这个技能指令的时候,已经拿到释放和影响的坐标等信息,只需和事件产生的那一刻的服务器存储的客户端坐标进行比对。

暂时只是思路,还没有真正调试,这些理想情况是对于网络好的人而言。

如果是状态同步,应该是不算玩家延迟的吧,一律都按服务器计算出的效果为准,A延迟高,B延迟低,AB同时下达攻击指令,服务器先收到B指令,则就是B攻击先于A, 小兵和野怪也一样,全是服务端算好攻击,发给全部客户端,至于延迟应该是客户端那边采取一些措施让玩家看起来比较正常,但是不会影响服务端发送过来的结果

状态帧同步吧?解决同步问题的本质思路还是帧同步

按我的理解,正常情况下,状态同步里寻路是后端也要写一套,由后端计算小兵的寻路结果,然后广播给所有前端移动。 但是你的情况是只在客户端写了一套寻路,后端没有写。那我觉得你可以用个不是很正统的方法做,选择一个玩家为房主,房主前端计算小兵寻路结果然后发给服务端,服务端再广播结果给所有客户端,然后客户端小兵再根据结果进行处理。房主掉线或者网卡要自动切换到其他玩家作为房主来处理这部分逻辑。当然这个做法缺点很多,建议还是后端写一套寻路处理小兵,除非你使用用帧同步

个人理解,对于多人联机游戏而言,玩家的操作,本质上都是“非权威输入”,只有当此输入被服务端接收后,才会变成“权威状态”(状态同步方案,服务端直接根据输入计算出状态)或“权威输入”(帧同步方案,由服务端转发至各个客户端,客户端再各自根据“权威输入”计算出“权威状态”)。

这边貌似是直接把玩家的输入,不经服务端验证,就直接当做一个“权威状态”去处理了,一般不建议这么做。

补充一个之前看过的介绍多人实时对战的文章,个人感觉写得挺好的:https://juejin.cn/post/7041560950897377293

2赞

对于小兵而言,比如5V5里面,10个客户端都有小兵。小兵的同步方案类似AI的感觉,我想了下还是得在服务器上计算小兵的移动路径。

比如在中路的情况,中路的小兵在不受影响的情况下几乎是一条直线,那么我将这条直线平分,平均将这条直线分为5个目标坐标点。然后我将这5个坐标点存储在服务器上。

假设现在游戏刚开始,服务器下发命令,让所有客户端生成小兵。比如一边有6个小兵,服务器现在有12个小兵的数据 + 单个小兵的5个目标坐标点。

生成的时候,服务器会先让小兵的目的地设置为第1个坐标点,计算出小兵的路径,然后服务器每隔一段时间循环分发这个路径点给客户端的小兵,客户端做的只是缓动这个小兵。

同时,服务器在小的时间间隔上不断判断单个小兵周围有没有敌人,包括敌方小兵和塔和英雄。
如果在小兵攻击范围内
——对于敌方塔而言,服务器立即改变小兵为攻击状态,并且停止移动,将这2个状态分发给所有客户端。
——对于敌方英雄和小兵而言,服务器立即改变小兵为攻击状态,停止移动,并设置移动目标点为敌方英雄和小兵,同时,计算新的路径点为当前移动目标点。

在我的观察来看,英雄联盟的小兵攻击的时候只会被攻击的目标死亡才打断。所以,接着上面的逻辑。
-——对于敌方塔而言,服务器立即改变小兵为攻击状态,停止移动,分发这2个状态给所有客户端小兵。服务器不断分发塔的血量给客户端。服务器启用小兵子弹发射的确认分发给客户端。小兵在服务器上不断进行攻击塔的逻辑,直到小兵死亡或者塔死亡才转换攻击目标。

写不下去了,感觉不太对 :upside_down_face:

有个比较简单的思路,就是,去除客户端,保证服务端的逻辑能够独立运行,模拟玩家观战,5v5双方都是电脑的场景。然后根据这个思路去看服务端需要哪些逻辑,缺了就补,写出来的东西就没问题了!:smile:

我理解你说,但是寻路插件怎么放到服务器上呢

这个就看是找一下有没有符合要求的第三方库,还是自己实现一个了。

或者说直接让客户端计算出路径,然后给服务器分发,那不是我之前的思路吗 :smiley:

对于多人联机而言,一般是需要通过精确计算来保证公平的,这个都是通过确定性库来保证的。所以一般是先找(或实现)一个确定性数学库,然后在此基础上,再实现寻路等算法。

如果想由客户端计算,那建议直接帧同步了。
后端仅转发来自客户端的操作输入(非状态数据),然后同步给客户端自己去算。
不过得注意,确定性、丢帧、追帧等问题了

而且我认为,英雄联盟给我的感觉就是服务器确认状态的,因为比如你按下了一个技能,服务器还没有接收到你的指令,这个时候你想放另一个技能,你按的时候是没任何反应的,相当于客户端给你锁住了,服务器只有确认了你的指令分发给所有人,你本地才能解锁按下一个技能

而且本地释放技能还会同时受到CD的判断和技能是否可以被打断的判断,加起来相当于3个flag标志

所以不可能把英雄的战斗逻辑放到服务器计算,不然直接炸了