GDC演讲翻译——看门狗2的载具同步
在《网络同步在游戏历史上的发展变化(五)——物理同步》一文中,我们提到了游戏看门狗2的物理同步策略,但是由于篇幅问题略过了不少技术细节。在这一篇文章中,我们会对该GDC演讲《Replicating Chaos: Vehicle Replication in Watch Dogs 2》做详细的翻译与梳理。 文章转自Funny David的知乎专栏(文末可点击原文链接查看),我根据自身理解对部分内容做了调整和优化。之前腾讯游戏团队也出过一篇讲物理载具的文章《手游中载具物理同步的实现方案》,基本的实现方式也是参考这个GDC分享。 下面是视频链接,长按图片识别二维码打开 ![]() 以下是GDC演讲分享的具体内容: ![]() 这是在GDC 2017上的一篇关于《看门狗2》中车辆系统同步的分享。 ![]() 上来先放了一段视频,描述Watch Dogs 2里“混乱”的车辆碰撞情况。(0:19) ![]() 然后讲了一下网络架构:没有中心服务器的P2P形式(状态同步),支持4个玩家,有很多实体要去同步,而且这些实体属于不同的分布式所有者。 文章中本地(Master)和复制方(replica)都是针对某个对象而言的。 假如有两个客户端,玩家A控制小车1,玩家B控制小车2。小车1在玩家A的客户端上就是主控的,小车2在玩家A的客户端上就是模拟的。同理,小车2在B客户端上就是主控的,小车1在B客户端上就是模拟的。 ![]() 一、载具同步的难点分析 ![]() 讲车辆同步的困难
![]() 涵盖内容:
二、轨迹调试工具 ![]() 轨迹调试工具是most important thing,所以放前面讲,通过调试工具可以看到物体移动的位置信息。 绿色的轨迹是车辆经过的真实路径,蓝色的是通过dead reckoning(外插值)预测的路径,红色的点是做同步的快照点(即从主控端Master同步过来的准确位置)。 ![]() 三、投影速度混合技术 接着讲最为标准的做法,就是投影速度混合(Projective Velocity Blending)。分享者说这个公式来自于wikipedia,追溯了下,最终来源是《Game Engine Gems 2》(游戏引擎精粹)这本书中的一篇文章《Believable Dead Reckoning for Networked Games 》。 首先大前提是使用航位推测(Dead reckoning)法来做位置的同步预测: 航位推测法(英语:Dead reckoning,缩写:DR)是一种利用现在物体位置及速度推定未来位置方向的航海技术,现已应用至许多交通技术层面,但容易受到误差累积的影响。英语中“Dead”是从“deduced(推导)”转化而来。这里就理解成位置预测就行。 然后一个运动学状态会(对应这里的快照)包含位置、速度、加速度、朝向和角速度。最简单的解决方案是基于线性物理的模拟: ![]() 这是高中物理的知识,但这里有一个问题就是我们有两个运动学状态,当前模拟的位置和最近收到的真实位置。一种解决方法是通过在这两个状态之间创建一条曲线来进行模拟,另外一个技术就是分享者选择的投影速度混合。 P0表示车辆所在位置,V0表示当前的速度,P0‘是上一个运动学状态的位置,V0'是上一个运行学状态的速度,Tt表示从T0开始经历过的时间长度,而头顶带个尖的T表示归一化之后的比例,即它是一个0-1之间的值。 ![]() ![]() 这样这里的几个公式就比较清晰了,先对速度做融合,然后使用融合后的速度计算位置Pt,注意这里已经在使用A0'的加速了,接着计算根据收到的运动学状态预算一个位置,最后根据归一化之后的时间比例对两个位置做差值融合。 跑出来的结果是这样的: ![]() 可以看出,绿色的原始轨迹是一个圆形,而蓝色的根据快照数据预测的结果是带有比较强的锯齿状的,通过视频可以看出车呈现出了很强烈的抖动。(5:30) ![]() 接着就讲twist(转弯)的内容了:
![]() 这样就很圆了……(7:45) 四、基于快照缓存的外插值和/或内插值? ![]() 接着说快照缓存的使用部分:(8:53)
![]() 这会带来“在不同客户端上因为位置不一致而导致结果不同”(A客户端上发生了碰撞,但是B客户端上没有发生碰撞),所以下面要解决这个问题。 ![]() 外插值和内插值的对比
依然可以从上一个收到的快照进行外插值
![]() ![]() 这里用视频讲解了具体效果,最好直接看视频更直观。(11:01) ![]() 时间偏移相关
根据车辆速度成比例改变,当车辆以较慢的速度运行的时候,错失碰撞的概率比较小,因此可以尽量使用内插值来做,这时候对应的就是增大时间偏移的值。 五、混合物理模拟来处理碰撞 ![]() 这样下来航位推测出来的轨迹就看着不错了,现在我们让车相撞看看 ![]() 看视频,车辆在相撞的时候会互相向后退,这和我们预期的不太一样。(13:22) ![]() 相撞的车应当都停住,或者把对方推开的力量更小一些。但是游戏里面,两边的车辆都推到很远的位置。 借助网络工具帮助我们逐帧来看发生了什么。 ![]() 这里是一段逐帧视频,白色的车在这里是第三方,它在黑车的客户端上发生碰撞之后,因为它自身没有开ragdoll(但其实有碰撞体),要等在它自己所在的客户端把碰撞之后的位置数据同步过来之后才会后退(这个时候还处于外插值的状态),于是它继续往前走,就把当前客户端用物理模拟(开了ragdoll)的那辆车给推到更远的位置去了。在白车自己的客户端上,黑车也有同样的行为,因此两辆车都产生了更大的碰撞后退效果,而实际上两个车相撞不应该产生如此大的位移。(14:30) ![]() 如何解决?
他会保持前进的状态直到一个新的包到达
因为没有人有碰撞的完整决定权(因为网络框架是P2P的)
![]() 但是问题还是要处理,这时候就引入了物理模拟融合(Physics Simulation Blending),即在发生碰撞前打开其他车的物理模拟(打开ragdoll),然后在模拟位置与快照发送的位置之间进行blend
关于Blend方案的问题:文中提到的"Physics Simulation Blending"是用本地模拟的与服务器快照进行混合。而本地计算是先行的,收到的服务器快照皆是过去的位置,所以混合的并不是同一时刻的位置,所以理论上可能会有一些不正常的情况(而且无法预测)。这里的例子都是汽车相撞然后一段时间内趋于静止,所以通常情况下没什么问题。 ![]() 融合参数调整(不同阶段调整物理模拟以及快照位置的权重)
图中展现了对于自行车和汽车,恢复的时间长度是不同的,其中汽车较重,相对需要更长的时间。 ![]() 效果已经不错了哦,这块要看视频。虽然不完美,还是会有一些推开的情况,但是没有之前那么远了。(19:10) ![]() 接下来说说进一步可能发生的问题——碰撞结果的不可预测性
其实由于看门狗2采用的带有预测的状态同步,所以误差是无法避免的,在物理模拟的参与下更难保证一致性,只能通过快照来纠正错误信息 ![]() 如何做到让在碰撞发生时将车辆放置到他们主机所在的位置呢?这里就要做碰撞预测了。
六、未解决的同步问题 ![]() 一些没解决的问题,其实有更多,这里只列举一部分。
![]() ![]() 静态碰撞的问题: 这块看视频更直观,真正的快照目标点在树的左侧,而碰撞模拟到了右侧,由于中间有一颗树的遮挡,这时候需要融合过来就很奇怪。(视频中可以看到剧烈的抖动,火花四射,然后一点点滑过去)(22:35)
他们最终的做法是如果发现你被挡住了,但是又无法移动到目标位置,就让你保持当前位置的,等有之后新的位置同步之后再处理。 ![]() 不同的时间偏移:
不同的时间偏移导致了在不同客户端上的碰撞效果不同,左侧的图车完全没碰到人,右侧的把人撞飞了。分享者说这块可以基于前面碰撞预测的同样思路来解决或者优化
![]() 恐怖谷效应:
![]() 七、未来的研究方向
卡尔曼滤波(Kalman filter) 卡尔曼滤波(Kalman filter)是一种高效的自回归滤波器,它能在存在诸多不确定性情况的组合信息中估计动态系统的状态,是一种强大的、通用性极强的工具。 https://zhuanlan.zhihu.com/p/39912633 ![]() 最后强调调试器的重要性,然后说虽然在这个过程中做了很多数学工作,是科学性的,但是依然有很多内容是需要从艺术/美术的视角去思考和改进的,毕竟要做到的最终结果是让玩家feeling good。(其实这个调试器本质是一个回放工具,需要把每一帧当前所有的对象位置以及行为信息都记录下来,方便后面做调试) 八、问答 问题:第一个问题关于timehop(跳时)的,如果某辆汽车在运行时切换了控制权(比如玩家A中途掉线,AI计算由客户端A切换到客户端B)如何处理这个跳时造成的问题? 回答:这个时候一般你会知道当前的汽车运行情况,比如车是沿着直线开的时候,就减速等着新的控制端计算位置逐渐追上去。 问题:车辆在爬坡之类的情况下的颠簸在同步方怎么表现,会限制外插值在一个平面么? 回答:一个解决方案是用物理模拟Z轴的变化,然后在车离地面比较近的情况下Z方向上不要外插值,但是比如飞跃到空中的时候还是需要切换到航位预测法来预测落点位置。 问题:似乎是在讨论是否有必要区分不同的物理对象,决定是否使用物理或者调整同步方式? 回答:其实在游戏里面是有区分的,比如自行车和汽车的物理模拟融合时的权重计算曲线不同。
|
原创文章,作者:,如若转载,请注明出处:https://www.3og.cn/53490.html