18.时域调制、飞行时间法 | GAMES204-计算成像 - P1 - GAMES-Webinar - BV1se4y1g7zt
好了啊,这个时间到了时间,欢迎亲爱的同学们来到gp 204,今天要给大家分享了一个主题是temple encoding的第一课就是time of flight,里面积。
我们整个呃temporary coding大概分几个part,第一个大的part就是嗯我们这种呃调制波主动发光了一个,他们flat image。
然后我们下节课会涉及到一些induct time flies,就是我们所说的continuous with time flies,当然这个continuous wave的time fly会比较复杂。
无论是从原理上到最后的处理上会比较复杂啊,这个可能会分两节课到三节课给大家详细的讲解这个time of flight image嗯,这里面到底是涉及一些哪些技术,到底需要哪些纠正,才能真正的运用到我们。
比如说车规啊,或者是工业的场景里面,因为我自己也做这个他们flaming的相机,所以说啊对这里面整套的链路会比较熟,这个是会给大家啊深刻的讲解一下这个整个他们flat imaging这一块。
也做了很多director flight,time of flight跟indeer flight的一些内容啊,今天就给大家分享一下这个temple encoding的第一课,但这个主动光发射照明之后。
我们还会讲到一些像,coded coded bucket camera,这个叫to bucket camera或者modebucket camera,或者是一些食欲的一些调制啊。
那个会是那一部分的一个temple encoding的课程的部分。
呃首先呢这一课会给先给大家呃介绍一下整个time fly的历史,然后再给大家就是从头推一遍,我们这个optical time resolve imaging的一个啊物理的一个模型。
我们通过这个物理的模型,我们知道这个基本的一个成像的一个模型,我们我们就可以去解决一些比如说dirt fly image的一些问题,然后呢说到这个飞行时间的一个成像啊。
我们就不得不再给大家设计一些相关的一些探测设备的呃,一些基础知识,还有一个现在的目前非常热门,非常主流的一个spider arcamera,就是single photo avenue的r啊。
翻译成汉语就是单光子雪崩光电二极管阵列啊,这个大家学光电的朋友可能会对这个啊,这个雪崩光电二极管会有一些印象,当然像那个光电倍增管呃,也是呃可以呃做到一个单光子响应。
但是国内边总管很难做成一个相机的一个呃二维的一个阵列,这个是非常困难的,然后会给大家讲一下整个呃单光子3d成像的一个案例,这个是一个非常经典的一个案例哈,首先呢说到这个探索fly成像的历史。
就是它的一个基本原理,就是我们啊比如说这个从这个物体a这个人a啊,然后到这个人b我这个时候因为以前我们把做光学成像,并没有考虑整个光飞行的一个速度问题,当然这个时候我们就认为光的速度是有限的啊。
这个时候今天我们就把这个光的速度啊,就认为它是有限的,它就是一个常数,虽然它很快啊,但是今天我们是有办法把它给测出来的,我们这个光诶这个从a发出去,然后经过了一段时间,唉。
我们这个最后这个光在这个t时间走的距离就是我们的v乘以t啊,这个v是考虑到介质的,就可以认为是c。
然后说到这个他们fly的美景,我们考虑到我们自然的情况,就是很多波呀,比如说我们这个可爱的这个小蝙蝠发出一速通,这个发出一束超声波,然后我探测比如说前面有没有昆虫啊,来探测这个回拨。
通过来这个回拨可以刺探到这个昆虫的一个三维位置,这样的话我们可爱的小蝙蝠就可以对这个昆虫来进行快速的捕食,但同样的一个呃就是超声成像的原理也发生在我们的呃水下,特别是海洋里面,比如说我们的啊。
这可爱的这个小海豚也是可以发出超声波啊,发出超声波啊,这样水下这个还是有一个问题一定的问题啊,水下因为它光学很难在水下传播,我们无论是激光啊,嗯还是有一些传统的光,因为我们之前上课也讲到过啊。
一个共聚焦的一个照明的一个kiss,就在水下成像啊,受到水体啊,特别是浑浊的影响,水下的光电成像是非常困难的,所以说嗯后来大家就是比如说大家的潜艇啊,鱼雷啊,都是通过仿生原理。
我们利用声波来进行物体的探测,当然这个声波也有它自己的局限性,就比如我们分辨率不高啊,就探测速度不够快,因为声波啊水里面大概就几百米的一个水平。
这是我们呃time of flight in nature的一个表现啊,这个他们fly不只是生,不只是啊光博啊,还有很多声波,但你其他的波地震波也是啊,大家很多啊,学那种地质的朋友啊。
会可能会经常用f t t t来去探测我们地质的结构啊,这个本质上也算是成像的一种啊,只是它不是光学成像。
当然说到这个整个我们测光的这个过程,但不得不得不提一个啊伟大的先驱者呢就是伽利略,那伽利略也是最早的呃,想办法去测这个光足的飞行速度哈,那个时候人能意识到这个光速光的速度是有限的,已经啊非常困难了。
因为我们并没有任何的知识呃,来去证明我们这个光是有它的速度是有限的,所以说这个呃伽利略当时就做了一个非常大胆的一个假设。
当我们到了1849年的时候,我们在fl都做了一个实验,他是怎么做实验,它是通过诶把一个镜子放到了8。633km之外,我们有一个光源,然后在一个观察者这,我们可以用手去掐这个表哈,去掐这个表。
然后来呃最后算一下这个往返的这么一段的一个时间,当然那个年代哈我们就是心虚了算了,我来回8。3km这么一个需要花大概58ms的一个时间啊,那个时候这个大家设备非常简陋啊,就是无论是秒表啊,还是观察者呀。
还是我们触发的这个啊是非常简陋的,那个时候嗯就没有办法很精准的测量,我们这个呃8。3km来回的这么一个时间哈,这个时间差是非常难测的。
后来啊就是这个老哥对这个整个实验进行了一个升级。
因为我们很难去控制这个开关的一个嗯就是精准的计时吧,我们就是以前的那些表啊,要记到呃毫秒微秒是非常困难的,不像现在我们点一下就可以记得非常精确,那个时候他用了什么办法呢,他用了一个呃比较密的齿轮。
对我们知道这个齿轮转一周大概是什么速度诶,我这个光打出去被这个齿轮的一个叶片遮挡,然后再返回来被观察者知道诶,我们就可以通过这个齿轮来放大时间的精度,好放放大时间的精度。
通过这样呢我们就可以拿到一束一束pose的一个light,就是我们呃这种pose的light,诶这个时候通过这个齿轮啊,大概当时用了720个齿的一个齿轮,然后欧米伽速度是256转,756转每分钟。
最后大家算得了一个呃3。15乘以十的八次方的一个速度,当然这个速度已经是非常接近真实的光速了,可以达到5%的一个accuracy,当然这个要说到这个测这种嗯就测光速这个实验哈。
就是以前呢可能大家做过那个物理竞赛的同学们可能看到过这个题啊,它是通过一个旋转的一个八棱镜啊,也不是八棱镜八倍镜了,诶我通过这个八面镜的一个旋转来去精确地放大我们这个时间的弧度。
时间的这个呃计时的一个精度啊,当然那个时候也都是比较古早的一些做法,测试时间不是特别精确,我们可以到5%的一个光速的一个误差。
当说到我们呃要本身哈,我们要回顾一下这个整个广场的一个方程。
当然我们前几节课我们讲到了,我们这个全光函数,就我们自然的一个光大概是有九个维度吧,我们目前认为是九个维度,将这个全国函数到底有多少维度,一直大家都没有一个定论,我们课上就认为是九个维度。
我们可以看左边这张图,我们他们resolution就从最早的古早的毫秒级呀,到微秒级啊,到纳秒级啊,到今天呢我们的测量精度可以到皮秒级,就有一些产品嗯,像pico count啊。
叫叫叫什么count都想不起来了,欧洲的一家公司,它的一个spy的传感器是可以做到50秒的一个呃,就是tom jor就是50秒的一个误差,当然我们通过一些算法优化。
可以做到一个sao second的一个呃,一个呃小people sep的一个精度啊,就我们知道一个皮秒光只走了0。3个毫米,一个来回时间不是0。3mm,一个来回时间是0。15mm。
这个精确度是非常高的哈,但为了我们获得有时候获得更多的维度,我们有时候经常会用到multiview,比如像双目啊或多木啊,双目经典就是双目立体相机诶,多目就是我们之前看到的一些呃光场相机的阵列啊。
这个就属于多目的一个范畴啊,唉我们最后实际上呃是想把更高维度的一个信息恢复出来,当然我们今天讲到了一个碳膜,fly体面积是通过时间的维度来获取我物体的呃就是每个点啊,在三维空间中的一个呃深度信息哈。
我们可以直接测量就是一个呃光的来回来测量这个深度信息,咱说的方法上我们就五花八门啊,我们可以通过物理学的方法呀,或者是就optimization的方法诶。
各种各样的东西来把我们最后想要的一个啊三维模型来呈现出来,哎这个图接力了,最早最早就是像伽利略啊,roman啊,牛牛顿呢就发现了这个光在物理传播中的性质诶。
到了father le计算了一个啊那个光的一个传播速度诶,到了爱因斯坦发现了光电效应,我们就可以通过这个光电效应来来做我们的光学传感器,1969年就是70年代初的,那时候。
c c d跟cmos技术出现了,就我们真正的呃有了图像传感器,当然到了最近这20年吧,就是2000亿以后,我们就有了一些高精度的一些带有计时功能的这个图像传感器啊,还有一个time flix ming。
这是一个失败的,这个我们后面会呃从一些物理原理上来给大家深度的剖析,我们这个今天就开始给大家正式的去讲解这个optical time resolve imaging啊。
就是我们通过呃光学的一个方法来测量光的一些呃,在时间维度上的调制与解调哈,就这是我们目前为止呃一些呃常见的一个time of time resolve imaging hardware。
我们git camera,这是一个phoenix做了一个git camera,它通过一个快速的一个g,快速的一个ga来实现这个我们在呃时间维度上的检测,当然啊这是一种传统的一种啊摄像机啊。
它只是它的那个呃这个git速度会比较快,我可以在某一个瞬间打开,然后在一个很短的一个时间内关上那另一种常见的器件呢,但现在也不是特别成熟,没有大规模产业化啊,这个就是sparr。
就是single photo ma lei do,single photo mileage do的a也就是呃所谓的光电倍增管啊,不对,这个雪崩光电二极管啊,把它做成阵列。
就是一个image sensor,他是工作原理是什么呢,是我的一个呃这个photo die的公司都在反向击穿区诶,我一个光子来了,我去触发这个啊血崩管诶,触发他的血崩效应,一个光子来了,然后产生两个电。
产生一个电子,一个电子在触发两个电子,三个电子,然后像那种链式反应一样,我就因为他是工作在反向击穿区嘛,它非常容易雪崩诶,这个时候一个光子就可以触发它雪崩诶,我整个电路就击穿了。
击穿了就可以产生一个非常强的一个电流脉冲,这个时候我们可以通过后面的一个电路来把这个脉冲给记住,这样的话我们就可以把一个模拟的一个光子的检测,比如说像我们传统的一个摄像机。
它是对电荷对在那个就井里面去积分,但是这个spidery就是来一个光子产生一个技术诶,这个时候我们就有了技术型相机,这就也就是从模拟到数字的一个月变啊,这是一个呃这是一个伟大的时代的进步哈。
它类似的原理哈,大家可以关注一下,还有一种呃类似于这种spider的,它也是一种脉冲型相机啊,当然跟这个原理不是特别一样,他是用这种传统的呃这个呃这个cmos或ccd的一个传感器。
我们后面再跟着一个快速的比较器,这个时候也是有一个就也是一种技术型相机啊,当然这种呃也有这种spa的呃,做不到的地方,比如spider,我们有死去时间呀,像这种呃通过这种比较气的,就没有这种死去的问题。
这个是呃北大的黄铁军老师有一个叫sparking camera,大家可以关注一下那个技术哎,挺有意思的,大家同学感兴趣的话,也可以联系黄老师去做一下这一块的,有search啊,比较高级的一些传感器哈。
就是这个光电倍增管,这光电灯管一经问世就惊为天人啊,他是通过一个什么原理呢,它有一个阴极射线,一个阴极,我一个光子打到这个阴极上,就会产生一对电子,然后我们中间会有很多的电极。
然后又产生更多的一些电子诶,再轰击那个电极,产生更多的电子哎,最后这个东西就形成了一种叫光电倍增管的东西,当然这个光电绿灯管就是我们上学那会儿还只有日本的这个哈巴玛索,也就是日本的冰松诶。
可以生产这种光电倍增管啊,当然这个是比较难做成阵列的哈,目前大部分的一个光电倍增管都是单个的一个呃,作为一个单管使用好,但这个玩意儿也比较容易坏,所以后来呃这个spider array就占据了上风了。
这个光电倍增管本身呢,它的一个响应速度跟它的一个噪声水平都是非常出色的,呃但是就是因为它很难集成的一个问题啊,就渐渐的被spa的呃占据了上风,此外本身还有一个大cos,就是我黑的时候也是会有黑暗技术的。
但是他有他就是呃体积小,易于集成,我随着工艺的不断进步,哎我的造成水平也可以不断的向光电倍增管去迈进,然后另一种东西呢就叫呃log in sensor。
也就是我们所说的一个continuous wave,他们fly sensor,唉,这是我们自己做的一款产品啊,这应该是目前深度相机里面的一个呃比较呃高段位的一个产品。
这个是通过一个呃光飞行的一个相位的测量来去估算它的一个深度,这个我们下节课会讲到这个lock in sensor,也就是continuous wave sensor的一个原理。
那最后一种a这种是非常非常昂贵的一种相机,诶,这个叫rike camera,这个我最早以前看过一篇论文啊,就是呃mit的romance russia的一个就是我们测这个猫可能大家还有印象哈。
就是一个光打过了一个可口可乐的瓶子啊,那个过程就是一个street camera记,就是记录下来的,我们后面会讲到这个条纹相机到底是怎么工作的,这是一个非常有意思的一个啊,这个人类的伟大发明了。
当然我们的整个的一个time resd,这个formation model就是我们本身光线它有自己的一个传播方程,我们即为pt这个光线打到我们的场景啊。
就是无论是啊一个你的就是你的发射出来的光源p t是什么样子诶,我们它会有一个呃场景对它的一个响应,我们记为ht跟t prime,经过我们这个reflectance,就是经过我们这个场景的一个反射哈。
表面的材料性质啊,我们这个就可以把它记为rt,这个时候就经过我们的一个镜头,再到我们的传感器,我们本身的镜头加上传感器啊,本身这个是有一个呃叫device response function。
我们记为f t t prime,这个是我们还是停留在我们就是传感器内部的情况诶,我们这个时候就可以通过a d c啊,就拿到一个management,就是也不是a d c啊,就是我们最后一个模拟信号。
而我在经过我的一个呃这个传感器,无论是spa呀还是一个a d c,你就可以把它量化拿到一个数字的一个嗯就是采样的一个结果哈,我们在通过这个数字采样的结果来经过一定的一个呃重建的一些算法。
我们就可以把这个same response function,也就是我们最后想要的重建的一个场景的一个情况来来对它进行恢复,这是整个的一个完整的一个tamara soft image的一个基本链路哈。
基本上所有的他们resolve image都是要follow我们这整个的一套流程,当然虽然他最后的处理方法啊会打通,会就是很不一样,说到这个problem function呢。
也就是我们最后发出来的光源到底是个什么样子,其实啊这个我们其实最后我们的激光器啊,其实发出来的光它不好说哈,他不好说,就我们通常认为就是简单一点,就是我们比如说一个一毫瓦峰值功率的一个皮秒激光器。
我通常工作在就是正常的工作区间的时候,我们可以认为它是一个近似的高斯模型啊,它还有自己的半高宽哈,我们要呃这个给不一样的功率,它会有不一样的半高宽,当然我们比如说这个皮秒激光器激光功率特别高的时候。
我们看右边哈,看到一些虚线,比如说我们这个这个这个3。7毫瓦哈,3。7毫瓦,这个功率最高的,这个时候诶,我这个整个的光功率高了,但是我的峰值功率并没有高太多。
因为我的整个的这个发出去这个激光的一个promise function,他受到这个本身半导体工艺啊,或者是呃你这个锁模调q啊,那种固体激光器啊,或者是气体不行哈,气体那个速度太慢了。
受到它的本身半导体或固体激光器的一个工艺问题,它的那个它的那个波形啊,就会有很多次刺激的一些调刺激的一些波哈,这个叠加在一起诶,这个时候我们整个形状就不是高斯了嘛,我们觉得高斯挺好,高斯挺好。
但是你最后你做不到是吧,这个时候咋办呢,这个没有办法,大家无论怎么样,还是要把这个波形记住,因为这个是你呃最基本的一个最基本的一个啊,那个就发出去的一个problem嘛,当然我们最后描述的时候哎。
通常是可以,你可以用一个be plan来去描述它,然后呢我们这个基本上我们有一个高斯的底儿,也可以用一个multi高深或者是一个高深。
expotential mixture的一个model来描述我们的一个probing function啊,这个一旦出面没有出面,同学问了一个continuous wave。
怎么解决face working的问题,诶这个我们还真搞过哈,这个大概有两种方法,第一种方法就是那么降低频率啊,就比如说100Hz的100兆的一个100兆的一个这个光波,我们打出去之后。
我们能测量的范围是1。5米,哎你要是偷个懒呢,你把这个频率降低,你降到十就是十兆赫兹,这时候我们可以测量的一个wpp的范围就是15米,但另一种方法就是我们选取两种不一样的频率。
我它的最小公倍数就是它的测量范围啊,我们这个比如说选到60兆等100兆,一个是2。5米,一个是1。5米,他俩那个最小公倍数啊是7。5,也就是说我们这时候测量范围可以到7。5米啊。
这个是可以解决face market的问题啊,这个ping function是怎么测得的啊,这个是可以用嗯,一般是用一个非常高精度的一个spa或者是一个管理民族管去测它,这个是用一个单点的去测。
当然你要是时间分辨率特别高的话,也不好测,所以说我们拿到了profile,通常就是嗯几10p秒到几百平秒的这么一个啊这么一个分辨率,当然如果大家有钱的话,可以搞个条纹相机哈。
这个可以是到零点几几秒的一个呃,这个这个时间分辨率哈,它是牺牲了一个空间维度来换取时间的一个思想,这个我后面会讲到,那she says restaurant function,这个有时候也掉sf啊。
这个没啥,它就是一个这么个响应,来我们来说到关键的地方,就是我们发射出我们这个先考虑这个direct flag,面镜通常是打出一个pose,就我们现在都假设高斯哈回来发出去是高斯回来还是高斯。
但是举个例子啊,我们当我们遇到了墙角呢,我们俩会经过两次反射,或者是就一根光哈,只能说就光用根说这是不对,一根光线诶,我打过去再经过另一个墙面再反射回来。
只有我整个传感器是接收到了直接光和间接光的一个叠加,这个时候我们就可以看到这是两个高斯的一个叠加,但还有一种情况就是我的墙角比较小,诶,这个时候诶就会有一个这么尾巴的那种感觉哈。
这个也会产生尾巴一个感觉,然后下面进入今天的一个正式的主题,叫direct time of flight image,假设我们有一个光源哈,这一个光源就一般是激光,可能是皮秒激光呢,也可能是纳秒激光。
就产生一个pose哈,诶我就产生一个pose,这个pose飞飞飞飞到这个场景上,哎,经过反射,我们最后在我们的一个图像传感器上就测到了这个pose是吧。
本身呢实际上我们这个emit的一个light pose经过一定的时间传播,诶,我飞飞飞,直到被这个呃这个这个就是图像传感器诶捕捉到,就是我们相机捕捉到诶。
这个时候我们这个假设这个source跟这个参数行系在一起哈,这个画出来画到b块也没问题啊,这个光总共飞行了,从出发到回来这么两对,所以说我们到这个点的一个场景上,这个点的一个就是深度哈,叫depth。
实际上就是c a除以二套,对不对,这个就是它的一个呃这个它的一个深度好,这个套是他的那个周,这个周期f实际上就是f就是频率,就是光的一个调制频率,你可以就是只能理解为t分之一哈,t分之一哈。
诶这个时候我们就可以拿到诶这个最后的深度啊,这个写错了哈,这个应该是2c乘以套哈,大家注意一下,这个写错了,direct time fly image。
最基本的一个应用就是我们今天所谓的拉达好,还是flash的lia也好,都是一个呃基于直接time fly imaging的一个case,唉,这是我们一个呃比较好的一个叫叫阿狗的这个这这这个这个宅公司啊。
这不是这是cvpr的一篇论文哈,来做了一个lider才可以比较好的获得一个大范围空间内的一个点云,direct time flat imagine。
说起原理是非常简单的,但是考虑到我们器件本身诶,这个简单的问题就会变得复杂一些哈,我会讲到这个器件到底是为什么会变得复杂,首先我们考虑到直接方的时候。
我们这个sensor是可以拿到一个最短的第一个pose,基本上第一个pose最近的地方就是它的一个direct path,对不对,然后呢这个光还会被漫反射开,大家学会图形学的时候呃,会学到这个材料表面。
我们用一个b r d f function或者b s s d f function来描述这个呃,材料本身表面反射的一个性质哈,经过这个多次反射诶。
多次反射我们这个光啊就会收到一系列的啊这么一种多次反射的光啊,这个就很烦哈,也就是我们最后,收到了直接反射的一个光,我们可以记为这个红色的这个pose,这是我们直接测量的第一个intensity。
那这是模拟信号,没有量化,这个大家注意一下,后面多次反射的光通常是会产生一个呃非常这个形状也不确定啊,但是跟场景啊直接相关的一个播报哈,这个播报是会十分影响我们的这个距离的测量哈,这个怎么影响的呢。
说到这个打他们flaming,首先我们要说一下如何才能实现这个直接光的一个测量,首先哈我们要有一个比较好的光源,就是要拿到一个非常呃expensive的一个laser。
就是我们需要一个短波的一个pico second laser,同时呢这个它的峰值功率他一个一个脉冲啊,通常要一个到一个叫米卡,周二周二就叫赵焦耳级的一个量级哈,这个它的峰值功率是非常非常大的哈。
所以这个时候他是第一个要求,第二个要求呢是需要我们的测量设备,也就是我们的相机或者是一个啊一个条形的一个相机哈,那种便宜一些,这个它需要一个非常高速跟高高度的范围的一个呃测量能力哈。
高速就是因为我们时间分辨率越高,这样的话我们深度才可以测得更准,比如我一个p秒的一个呃一个p秒的一个抖动哈,我们的这个分辨率差的是0。3mm除以二,我一个纳秒抖动,这个好家伙就是呃0。
3乘一个1000哈,那就是30个厘米啊,30个厘米主要是15cm的误差,这个误差是非常吓人的,诶这个同学问到model deption影响大了呃,这个影响还是非常大的哈,这个呃需要大家后面的算法去处理。
要不处理的话,要简单的用个什么执行法啊,这个影响会非常大的,这个说到这个他们flat major,你换个说法,有时候也可以叫trinity,main,叫顺态成像哈。
就是我们最有名的例子就是一个light in flight image,就是我们记录光线是怎么在空间中飞行的啊,这个实验我以前也做过,是用我们自己的一个spider阵列啊。
跟自己的皮秒激光器一起来记录啊,这个光线到底是怎么飞行的啊,当时我是记录了一个诶这个光线聚焦的这么一个过程啊,本身呢就是我们这个超快速成像啊,就是它是一个非稳态的一个成像,这个我们是要记录到这个非稳态。
就是这个光在这个空间中传播到底是什么样子诶,我们也可以用这种原理来track,我们去来追踪我们这个播的一个拨弦在什么地方,就是我这一束波,我最前面那个波在什么地方,因为我光已经非常快了嘛。
当然这个就是等效于你对这种非常短的一个pose,短的lipose进行成像,我们的城乡基建本身也没有办法做到皮秒哈,我们可以用各种各样的一些啊啊idea啊,去实现这个更高的时间分辨率。
哪怕我们的七件诶顶多就到呃几个g啊,或者是几十个g啊,这个水平啊,我们电子器件比光的器件,那比光学的那个速度是差很多嘛,但是我们可以用各种各样的方法来来提升我们这个测量的一个,最小的时间分辨率能力哈。
但说到这个传送的e美景,其实最早的时候。
这个news and anderson这个人家最早是用那个干涉的办法来记录这个拨弦哈,这是比较古早的一个传送点,image,然后呢98年的时候他又用了一种干涉的办法来测这个transition v。
实际上就是测了一个物体的一个depth啊,这是我们用干涉早期,因为我们成像器件没有那么快,我们可以用啊这种呃眼干涉啊,或者是嗯好了,过税的方法来记录这个波前到了12年的时候啊。
这个mton就搞了一个这个looking around the corner这么一个论文哈,这个当时没引起了轰动,我记得我上高哎,不是我上大二大一大二大二吧,那年我上大二大二那会儿大家就看到一个新闻。
我这一个东西怎么能看到墙拐角后面的东西呢,是吧,这个怎么能看到全国卷后面的东西呢,当时呃就觉得非常不可思议啊,现在想想哎这个自己搞搞也可以,哈哈哈,然后到了13年啊。
这是我们组的一个叫菲利克菜的一个呃一个师兄哈,这个现在在普林斯顿做老师,当时我们是提出了一个用continues wave来做了一个time of flag,main的一个例子哈。
这个比那种three camera会便宜很多,我这个几百块钱的旗舰哎,就可以记录这个transition imaging,这个这个光到底是怎么传播的。
那这里面这些trick我们会后面再讲这个continuwave的地方,会讲到这个非常有意思,到了15年的时候,graphy就开始用spider旗舰哎来捕捉这个光线是怎么传播的了啊。
当然这个这个这个这个图是骗人的哈,这个图是后期渲染过去的,因为这个本身在呃在这个空气中,你这个光线怎么走是看不到的哈,就是看不到的,这个时候是用了它本身在光空间中激发那些粒子是非常弱的,你很难捕捉到哈。
这个是已经后期做了加工的,来给大家示意一下,然后到16年大家就可以把这些呃,spider器件进行了一个三维的一个成像,就是叫first phone image啊,印象很深。
那个时候我最早开始入门做科研的时候,用的就是这种spa相机,当然这个direct time flat美景还是有非常多的应用。
比如说我们最经典的应用就是looking around the corner,就是我们呃这个怎么样看到这个墙后面的一个东西啊,这个那大家感兴趣的话。
我会给大家专门开这么一节课来补一下这个look around the corner,到了后来呢到12年这个中的conner大家不满足,一直看到后面什么东西了,哎想要看到后面的三维场景是什么样子。
诶这个是looking around the corner in 3 d哈,到了18年哈,就是当时有一个师兄叫mt or two,诶。
那个时候他在斯坦福那会儿就做了一个real time的一个real time的一个look,around the corner的一个呃一个问题啊,一定要开哈,这个那就给大家讲一下。
look around the corner上,因为这个那就下节课给大家讲吧,这个直接就是属于这个direct time flat这一章了,但这玩意儿还是可以用于b2 d还是个测量哈,这个也很有意思诶。
我们这个sample经过一个define wall啊,这个经过一个光啊,经过这个一个漫反设备墙,再经过这个三口,再经过一个底层生活,我们通过这个来测诶,我们材料表面的一个b2 df。
当然还有一种就是我们这个光线传播的一个呃分析哈,这个也是一种啊,其中应用当然这个非常多哈,再给大家今天给大家讲这个3d好,然后这个在讲这个3d成像之前呢,还是想给大家就是说道一下这个条纹相机啊。
叫street camera,就是他这个思想啊,让我当时觉得非常惊艳,非常惊艳,本身呢就这个street camera这玩意儿,它一次只能捕捉到一条条纹,但是他用的是一个2d的一个相机。
我先给大家就是掰扯一下它这个整个相机的结构,最前面这个相机啊,它是一个就是一个铁片儿哈,一个铁片,铁片开了一道缝,也就是说我这个相机一次只能捕捉到一个送过来的一个信息啊,就一个一个条状的信息。
所以说这个也是这个street camera的一个名字的一个由由来哈,它叫条纹相机哈,因为他真的一次就只能捕捉一个条,后面呢条后面就是我们正常的透镜哈,然后本身呢我们这里面做了一个管子。
这个管呢也只开了一个缝,也就是说我能保证我进来的光啊,进来的光只能从这么一条缝啊,这么一条缝进到我们后面的一个装置,对这个缝进来之后啊,我们这个比如说这个光子,这一连串的一个光子哈,在12344根光哈。
四个光子按时间序列分别的去进入到这个缝啊,进入到这个缝第一个地方,这个地方就拿到了一个我们类似光电倍增管的一个阴极的一个地方,诶,打到这个阴极上,我们可以把这个光子变成电子。
同时呢我们这个地方用到一个呃,这个叫集,就是一个感光元件嘛,后面会跟一个c c d哈,这是对电子的一个响应的,一个就是类似于啊类似于我们那种嗯荧光的一种片子嘛,就是荧光的一个涂抹荧光的一个薄片。
这个时候我们加了一个高速swap的一个电厂啊,快速高速swap一个电厂,然后我们用这个电子,就是我们这是连续变化线性线性加压的一个变一个电厂,我们这12344个光子,每个依次按顺序变成电子诶。
我在不一样的时间上,我家的电厂的偏压不一样对吧,我们就是这个这个电厂啊,这位同学说的挺好啊,就是把通过电场把这个电子撕开行,撕开到另一个c c c开到一个空间维度上,然后呢通过撕开这个空间的维度。
我们最后用一个二维的相机,一个二维的原本沿着这个调的方向诶,还是这个调的一个维度,但是就比如说记为x,但是y的方向他就是记了我这个跟这个电场电压线性相关的一个啊,空间维度,大家仔细琢磨一下。
这就是我们牺牲了二维图像传感器的一个维度来换取他的时间啊,比如说这个时候我们用了一个672诶,乘以672的这么一个图像传感器,我通过电场呢把这个另一个维度转换成672个小份哈。
这个时候我们就拿到了一个x乘t的这么一个图像啊,对吧,这个就是这个基本的原理,就是牺牲了一个空间维度来换取时间分辨率啊,这个最后我们也可以扫描嘛,这个我们可以扫描这个二维的空间哈。
最后拿到一个xy t的q,那我每一刻我只捕捉到这么一个条文哈,这个这个非常有意思啊,这是一个假说,我们这个最后这玩意儿本身哈我可以做到啊,比如说是100平米的一个分辨率啊,我们电子没有那么快吗。
到实际到头了100平米的一个分辨率,你把它分成672分啊,你就是100平秒再除以600,你可以做到诶,零就是几百个飞秒的一个时间分辨率好,这个就诶非常非常有意思哈哈非常有意思。
这个就极大地提高了人类对时间的一个探测能力,当然我们讲一下我们的主角哈,因为这个呃spa才是呃这个spa,一个才是一个它的这个应用的一个范围更广泛的一个器件嘛,哎这位同学问电场的时间分辨率是多少啊。
这个一般哈,我们目前的电子器件嗯,大概几十个g到几百个g啊,大概是这么一个量级哈,当然这个你要线性变化的过程,它那个变化过程的一个斜坡啊,这个我们变化没问题啊,唉说到这个spa的传感器呢。
本身它有什么优点呢,它也是像关节倍增管一样,可以有单光子响应的能力哈,当第二个地方就是它可以有p秒量级的,大概是50秒到27秒的一个时间分配哈,这个然后第三个优点这个点也没写啊。
它是可以做cmos集成的,就是我们可以用cmos的工艺把它做成一个图像传感器,这款就是我用的第一款这个m p d的意大利啊,这个就叫米兰诺,好像是这跟米兰诺那个那那那个合作的一起的一个spider场景。
当时我用的可能是他们家的第三排,我非常清楚的记住他那个编号是第三台,买过来那个传感器连封装都没有,就裸片哈,裸片直接打线,打到电路板上的,这个非常早期本身呢跟我们一般的这个cmos图像传感器不大一样的。
是这个spider呢本身我们可以看到这个感光区域非常小哈,周围都是电路,我们要有时间转换电路啊,啊还有一些寄存器啊,这都是挺占地方的一些东西,也就导致了我们这个spider阵列想要做非常大的一个氛围。
也是非常困难的,哪怕到了今天啊这个e p f l的那个carbon,那老哥他们现在也就做到了1024x2024,这个分辨率还是四个五二拼起来的哈,这个呃很难做大。
本身它这个呃我们用cmos这个silicon cmos工艺加工出来之后,它这个过程啊就像一个雪崩的一个过程,诶,一个光子产生一个电子,一个电子触发其他电子,其他电荷,其他空穴再采用电子空空血。
然后像一个雪崩一样啊,就就把这个反向击穿在一个就是反向偏置的一个就是光电二极管,就把它给击穿了啊,就产生脉冲,它的一个timer solution可以大概是55~50匹秒。
本身呢这个spa器件啊其实还是有一个比较低的一个呃,dark countrys叫黑暗计数率,这个要给大家科普一下什么叫黑暗计数率哈,就是你这个相机,你这个技术型相机哈,你把前面那个相机盖给盖上了。
就是官方在全黑的情况下,它还是会有一定的信号输出啊,这个就是呃叫dark count,这个类似于我们cmos传感器的一个大current层,这个是一直会有的,但这个现在的基建啊。
这个大countries都比较低了,本身呢我们也可以对这个speed器件加一个git,也就是我在这个我在这个我在这个,然后加一个就选选通,在什么时候,是因为这些工艺的缺陷。
就是我经常我在工作在反向计算区的时候,我受到各种因素的影响,会产生一个就不是因为光子影响的雪崩,比如说有一些嗯不起眼的一些哪些地方的一些额蟹复合呀,呃或者一些电子空穴对的一些变化扰动啊。
或者加工的缺陷都会引起呃这种大胖子,而且每个大家买这个spider阵列的时候要注意哈,你最后用的时候,每个像素点的大counts可能不一样哈,这个大家用的时候一定要特别注意哈,就可以大家提前标定一下。
这个一般出厂完之后就定死了,就是每个pixel的一个dht race,这个是不一样的哈,然后本身最后呢要有一个给大家科普的地方,就是它会有一个死去时间,因为本身我们这个spa的器件啊工作在反向击穿区。
我是有一个电,有一个电容在给它供电,我击穿之后,我这个电容里面电荷就释放光了,结果把电容的一个电压给拉下去了,我想要再使这个器件控控制在反向击穿区,这个时候我就要求我对这个电荷进行充电。
在这个充电的过程中,我们这个本身这个这个speed器件呢就失能了,在这一时段叫不工作诶,这个时候大概充了这个时间需要到1~100纳秒之间,这段时间呢又叫死区时间啊,叫dead time。
这起的名字也非常形象哈,这叫dead time,speed器件本身呢相比于cmos呀,还有现在的一个event camera,还有一个就是quantuimage sensor。
quantuimac跟speed,就是我没有后面的技术电路哈,这个这个这个大家记住就好了,这个spa器件就现在它的动态范围可以做到非常大的,因为是我们是呃技术型相机嘛,它理论上理论上是无限的。
但实际上是有限的哈,这个因为非常high flag的时候,我们这个你死去就饱和了嘛,就饱和了,时间分辨率也可以做到非常高,但是而且可以对极暗的环境下都会有响应,因为我单公子就可以响应吗。
但是他这个数据复杂,他这每次都要出来一个time his gram,这个处理起来会非常困难,那这个耗电量也是比较大哈,也是比较大的。
cmos呢本身就是局限于这个wc range这个timer solution啊,当然对这个暗光情况下也不是很好,像我们这几年流行的一个叫event camera。
event camera本身呢呃呃它是只能捕捉到边缘动态范围很好啊,时间分配比较快,因为数据量少嘛,然后这个cos跟cmos也差不太多,因为这个都是面积钱啊,都是面积前就processing也还好啊。
本身呢但是他对这个暗光响应也不好,也不好,这个这跟cmos都是因为都是都是一家子哈,这都不是很好,这quarter image sensor呢就其他优点基本都有,但是就是cost也是非常高。
但是他那个时间分辨率还是不如spd,大家记住这几个啊,旗舰的区别本身呢我们传统的一个图像传感器啊,就是比如说100~1000个photo,我在经过这个光电二极管转化成电荷,我在这个井里面去积分啊。
但是单光子呢就是我来一个就产生一个脉冲,来一个产生一个脉冲,但说到这个speed我们要说一下,当然我们知道刚才讲到了,我们有1~100个纳秒的一个死去时间哈,就是我们一般可能呃遇到了七间。
大概是50纳秒的死去时间,但是就是我这工作一下,我50纳秒就不能工作了,这个时候我们怎么样来保证我们这个时间的测量精度呢,就我器件还是不是特别快哈,就哪怕现在最快最快的一个g最快的gg宽度也是呃。
我们之前用过最快的宽度,可能就是大概100个皮秒的一个gay的宽度啊,100个皮秒,我们这个光都走了嗯,100个平方光走了大几个厘米啊,这三四个厘米了,这分辨率不行啊。
所以说这个时候聪明的人类又想到了一个非常非常惊人的一个阿迪,这个是借鉴了,就是我们示波器里面借鉴了我们示波器里面有个叫等效采样,叫equivalent time,产品等效采样的一种原理。
就假设我们测量一个周期性的信号啊,就是下面这个input sign,我的器件没有办法做的特别快啊,但是我的相位延时可以做到非常精准,就我没有办法在一个周期内对我的这个信号进行一个完整的测量,怎么办呢。
怎么办呢,就我第一个周期测量这个信号的一个点,因为我是这个信号是周期性的,是可以重复的,第二个周期对这第一个周期产生一个微小的相移,再测一个点,再下一个周期再乘一个微小象一,再加一个点。
直到我经过足够多的周期啊,我把这一个周期性的信号的每一个点都凑过来了,最后形成了这么一个等效的一个波形的采样,这个我们也可以用诶,比如说我们示波器里面就可以用一个嗯。
大概几个g的带宽来获得上百g的一个等效材,大家比如说可能用到便宜点的那个示波器,100兆的一一百兆带宽,当然等效采样率是可以到实际的,就是我们可以到100倍左右的一个呃,就是等效时间的一个采样能力。
类似的原理,也就是我们今天讲到了一个呃time cosle搜索counting,这个跟等效采样的原理基本上是类似的,我们通过这种周期性的测量来精准的,就是但是我虽然时间分辨率到不了特别高。
但是我相位可以做到非常精准,它通过锁相环啊就可以产生一个大概20几秒精度的一个相移,这是我们本身器件所向环就可以做到的,我就牺牲时间,就是重复测量来换取时间的一个分辨率。
这也跟刚才是一camera呃不太一样,这是一种也是一种思想,一种相互牺牲的思想,刚才是牺牲一个呃空间维度来换取时间,这个是形成一个时间来换取时间来重复测量,这个呢我们是重复的打出来这个光波对吧。
我这个开启的时候诶,我这个光子可能在这个时候到了下一个周期,我就产生一个向移,这个git可以产生一个向仪诶,最后我可以把这个整个就是这个要采样了,这个像不断向移。
就是我最后的这个呃实际上就是我们的一个c的一个响应的一个方式,这样的话就可以极大的提高啊,我们这个时间上的一个分辨率啊,它思想就是重复测量,然后每个地方产生一个微小的相移。
但目前为止就是我们最高的一个起点哈,就是实验室的可以做到啊,100万像素就是1k乘以k的一个1024x1024啊,这个比较便宜点,商业化应用的就是iphone来的,大概就是一两百,大概这个分辨率好。
但这个来的还还还有一个小trick和当年拆解过哈,拆解过他是用他那个发光器件哈,是那种可以调制那种b的那个发光器件,嗯这个同学问这个周期性的信号是否可用,这个是没问题的,因为这个信号是你主动打出去的。
这个没问题的,compressive sensing,这个也没问题,这个你这个你就是一直在打这个光网,这个你这个pattern固定住,你一直在打这个光,也就是测量在这个pattern下的一个相机。
你换下一个binary python,你还是这么打光,它本身是嗯,你就相当于多形成一个位置,就是呃本身也就是在一个固定pn下的一个相仪嘛,然后你下一次测量再换一个python。
下一次测量再换一个python,把整个相位全部再扫一遍,这个compressive city是没有问题的,哎说到这个single photo的3d页面镜哈。
就我们呃大家要直接测量的这个来回呢也没啥意思哈,那我给大家说一下,这个直接测量这个来回有什么问题啊,就我们最简单的就直接诶一来一回,我一个stop watch来测量这个回拨的这个时间。
就我们这个time shift,比如说是这么多,我这个你这个来了这个光子就收回来的,光子呢就是这个样子,我们这个第一个光子产生一个脉冲的时候,我就第一个脉冲诶,我就想象到了好理论,好好。
这个就是我最好的一个位置哈,这个直接可以算深度,但这个玩意儿是有非常非常多的问题啊,这是理想的情况下是这个样子,但我们外面是不是有环境光呢,本身是不是有死区的,这些都是一个问题哈。
假如在我这个gate开启的时候,你的光线比较弱,光线比较弱哈,哎你这个第一个触发的这个光子,但是有可能是你你这个你就不知道你这个get开起来是哪个那个pose,导出去pos是哪个光子,触发这个嗯。
触发这个血崩哈,这个时候是第一个问题,当然是特别是光线比较强的时候哈,就我发出去这个pos的这个光线比较强的时候,我这个git开启,我基本上就是第一个光线非常强哈,我这个上升沿的过程中。
我这个就已经响应了,这个时候产生一种问题叫pull up,也就是光子堆积的这个响应,这个时候会让你的一个深度图像看到会有一种阶梯状的一种感觉哈,有没有办法呢,大家可能简单点的办法就是加个滤光片哈。
让他光想降下降下来,但本身这个你降下来会降低信噪比啊,玻璃门这个美好了,这个这个是真没办法,但除了像这种刚才讲到的这个pile up的问题啊,这个这个up本身也是死去的一个问题。
你这好家伙趴get期间第一个检测完之后,后面传说光子全都检测不到了哈,还有一个问题就是今天我们讲到的问题,环境光的问题哈,就哪怕你加一个很好的滤光片,我这个环境光始终是不可避免的啊。
到底是你的信号触发了这个雪崩呢,还是这个环境光触发了雪崩呢,这个时候你没有办法判断哈,没有办法判断,这个时候会对你的深度造成一个非常大的一个误差,然后怎么办呢,coherence getting。
这个有优势,但是就不如今天讲这个优势大哈,就是今天讲这个非常有意思啊,大家可以看一下,哎我们最基本的就是打出一个比较弱的一个光哈,经过一个人time shift,第一个pose唉在这个侧。
第二个pose,在这个测n个pose,我把这个统计出来一个他们his gram理想的情况下,我这个是不是飞行时间就是他理想的一个飞行时间呢,哎对理想的情况下是哈。
我就最后哎套乘以c除以二就拿到了我最后的一个深度啊,这个是理想的一个方向,但这个当我们遇到这种情况。
就是我们在非常黑的情况下是这么玩,是没有问题哈,是没有问题,它基本上就接近理想,没有环境光干扰,但是你想想我们要遇到这种问题啊,比如说就是白天啊,白天这个激光雷达这个跪了咋办哈,这个就很难。
还有就是我们对面来个大灯哈,你说没影响,但是你看那个大灯,激光雷达,看个大灯还是会受到影响,怎么办呢,这个时候我们的情况就变成什么样了。
我们还是本身我的信号还是这么一个波,但是我这个时候要受到一个环境光的干扰,我整体会有一个呃光线的偏执哈,我来了这个incident,除了我这个信号这个脉冲这个框子哈,还会有非常多的一个sunlight。
但是我这个时候get已经开启了,get已经开启了,他你这个环境光,太阳光这个光子一下就产生这个水波,计算了,后面的信号全都测不到了,是不是这是你环境光的一个干扰,这个时候你不好处理好,这个就非常难处理。
最后你拿到了一个你经过这n次测量,拿到一个time his gram,就拿到好家伙,是这么一个explential decay的一个模型哈,这个地方你看很肉眼看到还能看到这个信号。
但是你能判断这个信号到底是不是你的这个pose的这个来回,这个时候就变得非常困难,非常困难,这个时候来我们这个信号就完全淹没在我们这个环境,光的一个音响里面了,本身呢我们这个peek就非常定位了。
非常难定位,这个时候深度就就比较难以估量好,这是当时这古普塔仿了一个啊,这个仿了一个这个环境光的一个影响,没有太阳光的时候,我们可以看到这个三维测量是非常准的哈,非常准比较准哈,也不是说非常准比较准。
有了这个在2000多赫兹的一个强光源下,诶,我最后的这个最后的这个图像呢就会受到这个太阳光的影响,我前面有很多的点哈,就是我这个是离这个真实深度更近的一些点啊,更更就会产生一些更近的一些误差。
这就是太阳光带来的误触发行,这个通常是离你的一个相机呃,就是是是会使深度值偏小,然后这个error就变得非这个error非常大哈,这个这个大家可以明显的看到这个深度的一个error,那怎么办呢。
这个问题出来了,是不是得要办法解决呢,好这个诶,这个我们可以看到我们太阳光产生这个风筒,这即为白的哈,然后我们的主动光源,这个即为黑的,我们简单一点intuitive的方法。
我们降低这个我们增强我们增强哈,增强这个光源的一个强度,来降低太阳光的一个强度,然后再加一个absorption filter,加一个,那就是衰减衰减片哈,这个时候诶我加加了光源,这个成本变高了。
大家不高兴,同时这个激光对人眼安全是会有影响的,但这个时候呢它会有一定的提升,但是你这个太阳光被block了,你这个发射出的光也被block了,对不对,这个时候呢就会导致你的一个sn r非常低。
你最后测量出来了一个his gram,就是你也不知道哪个地方到底是不是是噪声啊,还是有太阳光,这个还是没有办法精准的定位,我这个深度这个咋办呢,这个同学们有没有思路呢。
这个想一想我如何解决这个太阳光的干扰呢,这个想给大家抛出来一个问题哈,这个如何诶这个降低这个太阳光对这个git的一个太阳光,光子对它的一个干扰,有没有思路。
这个我们就是现在讲到了今天的一个非常关键的一个地方,叫异步的一个单光子的一个3d成像啊,pollation这个搞不定的,这个太阳也是全片的嘛,对不对,你顶多是呃你你你这个偏振啊,这好多同学说偏振。
你这个给他一个,比如说你打了一个激光是偏振的,你加一个偏振片,你顶太阳光顶多削一半吧,这个也不行了是吧,特殊频率也不行,你本身打了这一个,比如说你你这个太阳光谱挺全的哈,你用特殊频率。
你还要考虑器件的问题,器件的响应你归基本上到1100就到头了,你有那种呃像那种三五组化合物啊,你到了这个一点几微米的一个频率,但是那个气垫不好集成造成大,但这个问题就是我们有真正的一种方法。
就是异步的一个弹弓子3d成像,用这种方法来解决对环境光的干扰,像我们呃他的这种他起了个名字叫k observation哈,这个也没有汉语翻译,我就不翻译了哈。
本身我们最后拿到了一个统计的一个his gram,就从我们这个sensor开始测量的时候,它会嗯不断的衰减诶,对不对,这是我实际的,我要在这个时候给它开启,然后我最后实际测量的模型可能这样哎。
中间这个还不能是光线特别强的时候,光线这个特别强的时候,那这就是一个直线,这后面就没了,我就我就第一个刚开的时候就被响应了,这个情况更坏,这个时候还是稍微好一点的哈,这个时候咋解决呢。
因为我们之前在做处理的时候,总是在这个这个位置开启这个g,我就是n次测量,每次都是在这个地方开启gate,我能不能第一次测量在这个地方开启git,然后第二次测量在这个地方开启gate呢。
因为我们这象仪是可以控制的嘛,对不对,唉利用这个思想就我们知道哈,在这个时候开启这个gate,然后最后测到了这个信号的概率非常低哈,但是我们在离这个信号非常近的时候,我们是有很大的概率来测到这个呃。
我们发射数据信号返回来的波的,对不对,这个时候但是我们又没有办法知道我这个sensor到底是啥时候该开,啥时候不该开,是不是大家没有办法知道我这个sr什么时候该开启,什么时候该给这个get。
是能这个不知道哈,不知道不知道,咱就咱就扫呗,在这整个时间都干预哈,当然我们这是第一个pose,就是我们第一次测量的时候,诶是这个样子对吧,诶我把这个这个时候我把这个相位,比如说整个测量周期。
我一个搞一个像一哈,搞一个像仪,第一个时候它的一个啊,这是受完全太阳光的影响啊,这是一个太阳光衰减的一个过程哈,然后第二个第二次测量诶,他是从这儿开始衰减,而最后离这个pose也很近。
测到的概率是不是大一些哈,我们再分直到分个n份上,从sister start到这个呃pose非常近的时候,但整个的一个过程是什么样子呢,给大家看,不要眨眼诶,惊喜就在眼前,这是三次测量哈。
我们三次测量加在一起哈,这整个信号啊我们就统计出来his gram就变成这个样子哈,诶这是三次向移搞十次相移呢,哎大家有没有感觉到奇迹的发生哈,十字相移诶这个距离就越来越小,越来越小,越来越小。
100次呢我们刚看到诶,这个信号相比于我这个本身这个呃get的shift是变得非常明显了,这个时候信号到1400,哎基本上我到最后我要用1000次shift这个get产生shift啊。
哎这个时候我们这个最后的这个波发出来,这个波啊就非常容易的探索到了,对不对,这个奇迹发生了,我们就可以解决到这个太阳干扰的问题,这样他本质的思想是非常简单,就我把重复测量的时候。
每次的gate在一个位置,诶,我就干脆把这个g做一个扫描,呃,这个不是分段禁止降噪哈,这个是实际上是啊,这个叫异,这种叫异步异步的来,就是我们把这个太阳光的干扰把它干干扰成一个平均。
因为我太我我知道我们的环境光,它在一段时间内是一个固定的一个值嘛,这个时候我控制这个get it开启的时间,也就是呃控制在每一个时刻进来的光,对不对,有这个pose的时候,这个g就有这个pose的时候。
这个get开启了它整体的光强是比这一段只有太阳光要高的,我通过这样不断的shift就可以把这个time gram绘制出来之后,就可以拿到一个非常清晰的一个呃,pk就可以把这个深度值来提取出来。
好这个也是这2年的一个最近的一个工作哈,咱俩以前可能见到那个spider,肯定产品里面肯定没用上,这肯定是比较新的哈,我我也敢保证这个目前为止大部分的一个激光雷达也是没有用上的,这个同学们呃。
搞这个搞这个激光雷达以后可以试一下这个方法啊,这很有意思,这个类似hdr融合思想嗯,这个说像也像,说不像也不像,他本身是多个相位的一个测量,就是通过相位来把这个太阳光的干扰,通过相位的这个get的相机。
来把太阳光的干扰跟这个pk的这个信号信噪比之间的一个差异变大啊,他是这个思想,这个思想,当然这个相比我们之前哎这个传统的一个获取方法诶,这个信号就明显的变得非常有意思哈。
就是一个异步的一个菜单的一个方法,当然本身哈大家可以观测到一个测量的过程,哎每次产生一个相移行,产生一个向移,这个时候那第一段这个第一炮测完,这个就进四区了哈,这个就是等着哈,对吧,每次产生一个相仪。
每次产生一个相仪,最后我那个信号就可以跟环境光相比哈,就在那一个小的短的时刻内,我这个信号是比或者这个太阳光强的,最后就产生一个非常好的一个测量,最后通过实验呢,我们可以看到就左边这么一个场景诶。
通过这种传统的一个测量,我就简单的一个长曝光,哎我就看哎这个太太差了哈,这个它的m s e啊就很吓人哈,4。5cm就差了一个拳头的距离,然后呢就是传统的一个短曝光呢。
就是我就是刚才像刚才讲到了一个加一个删减片啊,这个摆的地方很好,那黑的地方更不行啊,这个地方全都是洞哈,也不好,m s变得更大了,误差变得更大了,4。7个厘米,通过这种异步测量的方法,就可以做到1。
2cm就可以做的比较精细了,但这个是太阳光下的一个实验哈,这是一个实际的时间在2万勒克斯的一个实验诶,传统的一个长一次长曝光5。6个厘米,像这种异步的就可以做到0。65cm。
但是大家注意到这个时候还是有问题哈,还没是没有解决这个公子堆积的问题哈,就我这个pose特别强的时候,我是第一个光子该触发他呢,还是第二个光子在触发他们,是不是理论上应该是我峰值的时候来触发这个呃。
这个这个g get就是这个spd信号来产生脉冲,这个时候我的时间是准的,对不对,但是我只要git开启,我前面那些呃,比如说这个上升期间。
这个上升延期间的光子也会触发我们最后这个spider 7年的一个工作号,这个时候你的相位就会不准了,也就是大家其实这个是我们可以做到大概毫米级的,就一两个就是一个毫米或者0。1mm一的一个精度的。
但是你要是不考虑这个公子堆积的问题,大概是零点几个厘米的一个精度好,这个大家可以注意一下,大家大家做科研的时候可能会遇到这种类似的情况,这个所以说这个direct flat major原理上比较简单哈。
但是这个里面这坑还是非常多的,你要能做出来越容易,但你要想做好的话呃还是挺困难的,所以说要鼓励大家多在这个方向去多研究一下哈,这个有非常多有意思的一些方法啊。
这个就给大家就是说了一下整个高精度的一个3d测量的一些呃,这种办法,比如现在很好的话,可以做到在1百米做到1mm的一个精度,这个这个表已经不准了,其实像我们自己做可以做到1mm左右的一个精度哈。
像triangular就是三角法,可以做到一个非常高的精度,就是0。1mm,但是它会随着距离的一个变长,它的精度会迅速的下降,这个single footo 3 d呢,这个是可以做到比较远的距离。
做到一个毫米的量级,当然现在continues wave,这个我们也可以做到,也可以做到传统雷达大概就是几厘米的一个进度吧,就当大家看的比较远哈,这个这个single风头这种异步的一个获取方法。
是可以提高一个数量级到两个数量级之间的一个精度的哈,大家搞雷达的同学可以试一试哈,我这个也很也很好奇哈,这个到底这个放到一个工业里面应用到底行不行啊,这个大家可以试一试好吧。
但这个就是那除了这个单光子成像呢。
除了像我们刚才讲到了一个呃这个这个异步的一个3d获取,我们还是可以有很多像lucnn corner,像这种玩法的,就是我们看到怎么看到一个墙后面的一个东西,那除了这个之外,就是生物荧光寿命成像。
怎么样成为成像这个荧光激发与衰减的一个过程,还有可以我们怎么样在一个scattering的一个media里面去采集哈,那个同学说呃。
cg同学说这个对这个look around the corner很感兴趣,那我们下节课就先不讲这个content view time fli,这个先讲这个啊。
先讲这个这个这个look around the corner这部分啊,这个鱼蛋粗面同学问两个top相机对照会有影响吗,这要看你两个相机有没有做处理哈,一般的话我们需要做同步来避开两个同时照射的时间。
但是如果两个top相机本身的频率就是他用的光的频率不一样,就没问题啊,比如一个941850没问题,那都是850的时候呢,这个就需要对相机进行同步,我们来控制两个相机有一个微小的时间差。
让这个光源开启的时间错开哈,这个时候就可以避免之间相互影响,但一般的话可能还好哈,这个这个影响还好,哪怕不同步的话也还好,那你不同步就没有办法,哎这个不好说哈,这个看谁家的,看谁家的相机了。
每个品牌这个最后做出来这个感觉都不一样,呃同波长的两个对射呃。
可能会有影响哈,这个,br df是具体测量过程,这个想听吗,想听可以,后面在那个special modation地方给大家加一下哈,这个属于另一个章节的一个课程,哎说到了今天收到了。
最后就给大家说一下这个single photo的一些camera哈,最经典的像switch speed,就i是做那个1024x1024的一个嗯,1024x104的400相机。
现在市面上可以卖的只有5月2x512号,就我们用的比较古早的,但这个是gate的比较门控的比较快的一个呃,比较快的一个就是我们这个可以做到20几秒,可能swiss bad不是门口的嗯,就慢为是门口的。
就是他那个可能精度没那么高,但是它的分辨率可以做很大,当时我们用这个m p d的大概是32x64的一个分辨率,好像这个oster la它是线扫的一个嗯,spa价钱大概是什么范围呢,嗯这个我知道啊。
但是我不太好给你们报价,因为这个当时我们买这些东西的时候,都签了保密协议的,大概就是几万欧元的一个价格,还有像这种vocal啊,放ja jo的,就vocal是一种spect j gj。
这个sweat不一样,它是一个框架,image sensor啊,这cos mage sensor,然后这个东西呢这个这个dot本身是嗯就没有后面的一些技术电路哈,没有技术电路。
这photom force也是一个唉,这个sweat做的很很很很很难受啊,用起来非常难受,还是sweet sweat跟mp d好用一些,啊这个同学问讲event camera。
event camera之前有讲过一阵的看法,没有讲底层原理是吧,这个可以借temple encoding讲一讲哈,这个可能后面会多拖两节哈,这个还要做心理准备,因为内容实在是太多了。
对最后我们single phone camera本身是个非常非常多的应用的。
像呃长距离的一个成像啊,像一些low power的成像,高端端范围的成像啊,还有一些极限的一些极暗的环境啊,比如说军事里面去用啊,也可以做到非常高精度的一个deft solution。
当然这里面的研究问题又非常多哈,嗯对这个做这些硬件不光是比较烧钱,他还是需要你各方面的人啊,比如说像你们组里需要做光学的呃,做电路的啊,做嵌入系统的,有时候可能要写写pg,要会会点vlog,唉。
算法你还得精通哈,你看这个组里面人都有,起码人员配置是要有的,然后第二个地方就是做实验是比较烧钱的哈,这个是真比较烧钱的,这个很多地方是没有条件做这些东西啊,但是大家没关系啊,大家想做的话。
可以联系我哈,我可以给大家做一些,啊这个今天我们讲的内容比较丰富哈。
这个讲了一下整个基本的一个light program function,还有个time resolve imaging formation model,最后给大家讲了几种啊相机哈。
它的一个基本原理就是以呃牺牲一个空间维度换时间,而第二个就是spa的相机,它是牺牲时间换时间,最后给大家讲了一个single photo,imaging的一个异步的一个3d成像的一个案例。
来解决这个环境光干扰的问题,对这个同学只是试一些对,所以说这个还是建议大家就专注一个领域好,就不要做太多哈,做太多这个他可能觉得做到1/3啊,这个花光了,这个也是经常事儿啊,就专注一个领域呢。
就是你这些设备啊啊软件硬件都经过长期的积累啊,你这个整套都搭齐了,但你要每个领域都涉及,这个就是比较海量的一个经费了,比如说我们以前做的那种d e啊,d o e,但那个时候条件比较好。
我们比如说上午呃设计完这个远程元件,我们下午就可以自己去那种超级店去流片哈,但是现在可能回国之后啊,这些条件可能没有那么好啊,因为这个确实是比较贵,大概一次要要真要算算钱的话,大概是几万美金的一个量啊。
这个slides链接的问题,我会待会下去检查一下,然后让人把这个slides更新一下,但你要做这种大型设备就更贵了哈,这个更贵了哈,所以说这个我的建议是让大家整个学术圈里面的资源就可以共享啊。
就大家尽量软件硬件啊,加工设备啊啊,能共享就尽量共享一下,这样的话每个人都可以专注每个人的问题啊,来不要这个嗯,每个人都每个学校每个人都搞一摊,就是浪费国家的一个资源,就是浪费国家很多钱。
这个就可以相互借鉴一下,就是把空闲的时间相互share一下啊,没问题,这个就是今天晚上回去,我就让他们给上传了,好今天的课程就到这里,同学们还有什么问题吗。
那下一次课就先啊,咱先讲一个那个就是looking around the corner a,这个我也挺想讲一下这个的,这个你说原理吧,还真挺简单的,它就是一个墙哈,你可以把墙作为传感器。
这是一个核心的思想,你就把墙造成传感器就好了,然后你那个本身透镜成像的一个过程,就是把你的墙变换到你的cs上,这个时候你墙就是你的传感器,好那同学没有问题,那今天的课程就到这里。
再次感谢大家来到games 204。
18.网络游戏的架构基础 (Part 1) | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV1La411o7kG
Hello,大家好,欢迎大家回到games104,现代游戏引擎的理论与实践,我是王希,哪个终于两周之后又和大家又见面了,哪个休息的很不错,然后呢,但是最后课程准备还是非常的,这个这个很多的事。
突然发现网络也是很复杂的,没关系,我们每一节课开始的时候,最近都是用我们的哪个T恤作为我们的开场了,对吧,这个T恤大家都很期待,告诉大家一个好消息,就是我们这个T恤的话呢,现在已经送去生产了。
大概可能还需要三周左右,所以大家千万要稍安勿躁啊,然后呢同学们哪个另外一个就是同学们的话,我们上一次上两次,我们哪个就是在我们的评论区里面,我们的留言的同学们,我们哪个已经挑出了我们幸运的小伙伴。
然后的话这是我们的名单,然后同学们都能找到我们课程组呢,就是在群里面加入我们的小秘书AMANDA对吧,然后他会把你的联系方式啊,你的地址告诉他,然后呢他我们会等这个T恤记好啊,打哪个印好之后。
我们就给大家寄过去,另外一个的话呢,就是说我们再想了一下,就是不只是在咱们B站课上留言,包括我们同学们做我们的作业,如果连续能做完两次作业,就做完两次作业的同学的话,我们课程组商量一下。
说也给大家发一个T恤做个纪念,因为其实每一个作业都比较难,它不像那么简单的一个算法对吧,然然后呢,因为考虑到大家现在时间,就是前一段时间特别的忙,要准备期末考试,所以呢我们非常贴心的把我们的课程的。
所有的deadline全部设到了8月31号,那8月30号第二天是什么,9月1号,也就是在开学前,大家把作业做好就可以了,那么大家加油啊,争取能够拿到我们的哪个课程组的T恤,那么OK另外一个的话呢。
其实自从我们开始这个稍等诶,我的这个翻译器好像有点坏了,稍等,那我要用鼠标了,稍等一下啊,啊完了完了,我今天哪个翻译器好像有问题没事,那然后的话呢,就是说其实呢最近这段时间我们开哪个开始。
我们的这个就是B站小留言的活动时,通讯给我留言留的蛮有意思的,包括有同学跟我们讲说我们这PKO的引擎的话,好像跟红猪宫崎骏的动画,红猪哪个你们的哪个一模一,哪个哪个哪个修飞机的飞机场一模一样,诶。
其实我听到这个留言之后,我自己今天下午还把哪个,宫崎骏的动画也看了一下,因为宫崎老爷子的动画片一直是我最喜欢的,我觉得真的他能给我们激发,我们心里面非常美好的东西,所以我觉得一如既往吧,还是那么感动。
然后的话呢其实同学们的留言中,我能感受到一种温暖温暖吧,因为其实我们在做这个104课程的时候,很多时候呢我们也不知道我们的目的是什么,说实话我也没有刻意的去想过,我们2014课程是目的是什么。
但是我觉得我希望同学们真的能够享受,这样的一个104课程的这样的一个快乐,也就是说呃大家的话呢在这个课程中的话呢,就是说真的能享受作为一个游戏引擎,做这样的一个就是说能够享受一下上帝的感觉。
你可以自由地创造这个世界,我并不一定要成为这个世界上最牛的游戏引擎,引擎的研发者对吧,如果我做那么一个小小的功能,诶,天空因为我变得很蓝,我看到了绚丽的彩霞,我看到我的小人按照我的方式去动起来了。
甚至开始跟我互动,那种快乐真的是发自内心的,我记得我在读书的时候,那个时候就开始去写游戏嘛,很小的时候在大学的时候,然后我记得那时我写了一个足球的AI游戏,然后我就看着他两边AI在踢足球,可以看一晚上。
就每天其实很无聊的,你就看左边右边啊,A队赢还是B队赢,当时我还特别有意思的说,这是中国队,这是美国队对吧,那我肯定会很很下意识的,把咱们中国队的这个球技调的那么强,那么一点点,虽然事实上是反的对吧。
那么其实这就是做游戏引擎的一个快乐,就是说你真的能够去创造这个世界,那另外的话呢就是说,所以我希望我们的同学们的话呢,能够真的尽情的享受这个过程,就是keep it simple,就是说不用太多的功力。
我学这门课的目的是什么啊,我我一定要怎么样对吧,相反就是说你真的享受这你们知识的乐趣,包括我自己在准备这个104课程的时候,我和我们的课程组,其实从一开始觉得压力满满啊,到现在其实已经变成了一种享受。
或者变成了一种生活状态,就是大家每个星期在一起就说诶,这一周我们要讲什么,那我们一起把所有这方面的知识都自己学一遍,然后我们一起讨论会,就问哎这个知识为什么是这样呢对吧,这个东西源头是什么呢。
其实我们也是在准备这个课程,一边准备一边跟大家一起去学习,所以啊我觉得做什么都是这样的,就是你去享受它就好,那么好好啦,那废话不多说,那还是回到我们同学们的关心的问题吧,其实哪个我们课程组选了几个。
同学们几个问题特别有意思,他就比如说有同学问我们说哎我们怎么看,就是这个deep learning和这个reinforcement learning的未来,就是这个深度学习和这个增强学习的未来。
其实这个问题它本身呢就是怎么说呢,我觉得呃有点微妙,因为深度学习只是一种方法对吧,我猜这个同学主要问的是说诶,你是无监督的学习,还是这个有监督的学习是为了,其实这个从呃目前来讲的话呢。
我觉得很多的大家都在debate,就是说比如说同样对AI大佬,比如说我们像demand的话,他其实用的还是有监督的学习多一点,那么比如像哪个就是哪个这样子OpenAI的话。
它更像是这种就是增强学习多一点,那么其实这里面大家到现在还在,很多的方法都在讨论,但我个人看啊,就是说其实大家都会去想,就是我们的人类的智商,比如像我一直在思考,说什么时候。
有一天我们人类真的能实现强人工智能对吧,那我觉得最好的一个类比就是我们人类自己嘛,那我们人类的学习知识,是有监督的还是无监督的呢,其实很难讲,因为大家会觉得我们人类很厉害。
我们大部分时候都无监督自己去学会了,对不对,但实际上我觉得上天在我们的大脑中,其实不对应了很多东西,比如说小时候我们做错了事,我们的爸妈会对我们说啊,你这做的不对,你通过他的表情。
通过他的哪个哪个不开心的脸,我们就知道我们可能做错了对吧,他很开心的,暂时我们我们就知道我们做对了,其实我觉得我们的智力是有至少在早期吧,是有很强的监督学习让我们形成的对吧。
那么未来再往后的话是不是无监督学习呢,我觉得这是另外一件更有意思的事情了,比如说我们学会了下围棋呢,很多时候我们自己就会慢慢的,摸索很多的技术了,所以我觉得这件事情的话呢,呃我作为一个非常业余的。
这个就是说深度学习的这个,这个业余观察者的话,我认为就是说我们很难给出判哪个判断,但我认为就是说同学们可能对这件事情,要保持一定开放性,就是很多时候大家会在想说,就是有一种心态,就是我们要押宝押。
对对吧,但其实我觉得在很多时候,我们可以保持一种开放性,什么知识我们的学一点,而且呢就是其实大家看下,我们游戏引擎课有个特点是什么呢,就是实用主义,就是对于我这个specific的问题。
他用哪个方法是最好最快的,能帮我解决,我就用哪个方法,就像我们上次讲讲,哪个就是哪个游戏AI这个课的时候,我们就讲的就是说虽然像deep learning啊,像哪个就是监督学习,无监督学习。
其实非常的强悍,也非常的美妙,对不对,但实际上在解决很多游戏里的问题啊,有有的时候你可能用一些最基础的一些AI的,算法和工具就能解决了,所以那个时候你就不要上,不需要上那么复杂花哨的东西,对好的。
那么另外一个同学也在问我们,就是说呃就是游戏的AI模块,那么就是当游戏这个就是说版本更新的时候,AI模块是不是也是要相应的剧情版本更新,那实际上的话呢就是说这个问题不一定。
那因为就是首先AI确实和游戏逻辑,游戏业务深度绑定的,原则上来讲,就是说如果游戏的逻辑发生变化的话,AI有些东西需要发生变化,但实际上的话呢AI跟这个世界的连接。
我们很多时候是用他的perception,就是你对世界的认知对吧,观察你对世界观察多少个变量,这些变量如果没有发生变化的话,你的决策依据其实不会发生太大的变化,除非你决定修改他的行为,那么第二个就是说。
你反向的作用于这个游戏世界,就是说我能做多少种动作,如果AI体能做的还是这种70种动作,不会有变化的话,那其实游戏版本更新的时候,AI原则上其实是可以不用更新的,但是现在在现代游戏引擎中的话呢。
很多时候我们的游戏的AI,比如说我们用数据或者是我们用脚本去配置好,那么实际上的话呢,这些数据和脚本它并不需要,每次游戏版本升级了,我就要更新一次对吧,除非你像我刚才讲的说。
哎我对世界的这个state的表达发生了变化,或者说呢唉我能做的动作增加了或者减少了,那有些脚本可能相应的更新,那么包括如果我是用这个深度学习的方法,那假设我实质性的战场策略发生变化的时候。
我这个AI系统本身也会升级,但其实呢现在的很多游戏里面啊,我们的这个游戏上线之后,我们一边会用AI指导电脑打游戏,其实一方面我也没觉得,不停的抓取真实游戏的数据。
然后呢用它来training我们的那最后一个问题,就是同学问我一个,这应该是很很有趣的一个问题啊,就是哪个DLSS这个算法到底是怎么回事,首先的话呢本来我们想的高级课游戏讲的东西。
但这东西其实非常的复杂,就是DRS的话,那就是deep learning super sampling对吧,那么其实就是基于深度学习的超采样,这个东西为什么很有用呢,就像我们前面讲的。
就是说我们现在的rendering对吧,比如说我们一个4K屏,8K屏,那上来将近8K屏多少多少哪个像素了,应该是超过接近上亿的像素了吧,那这样大家就很郁闷了对吧,那我就一个个的渲染这个显卡都崩掉了。
那DRS这个算法好处是什么呢,就是你可以用一个比如说呃,比如说720P或者1080P的东西,我能够把它upscale成4K甚至8K的画面,它的技术原理是什么呢,就是最近大家在哪个B站上特别火的一个。
一类视频是什么,就是叫啊老照片,黑白照片对吧,高清还原,现在还有什么高清AI修复数字版,其实他用的都是类似的原理,就是说我其实因为人都很聪明,就是如果我找一个有经验的画师,我给你一个模糊的老照片。
他可以去想象和修补,那你们他的光影和那些细节,包括人的,比如说皮肤的肌理,衣服的肌理,人的动作的细节,那这样就把这个画面修复起来了,它其实就是知识深度学习最强的一个东西,那么第二次的话呢。
它实际上是对这个游戏的画面,不仅是在空间域上进行采样,就比如说你虽然像素很低诶,我从你周边的整个情况猜出来,你大概表达的是一片树叶,你大概表达的是一个人脸的皮肤,或者是一个石头的纹理对吧。
或者大理石什么东西,那么也可以还要从时域上叫temporal上去采样,就是在这一帧和下一帧之间,我去找你的关联关系,其实DRS的话现在已经好像是如果没记错的话,已经是2。0了吧。
就是这套算法实话实说做的是非常非常的强,就是说我们和很多哪个做rendering的朋友,去交流的时候,他们说其实第一代的算法,其实很多人都应该能够模拟出来,做出来效果差不多。
但是第二代算法什么他做到了什么呢,做到了,就是说哎我已经跟特定游戏没有太大关系了,这里面就讲一下深度学习,有一个很有意思的点,就是说你把比如说我是一个花里颜色,花里胡哨的FPS游戏对吧。
比如像OVERWATCH,我训练出来的这种超采样的东西,和我做一个非常写实风的,比如说哪个上古卷轴这种诶,我选出来的哪个超采算法,是不是有那么一丢丢区别呢,对吧,是完全不一样,但是呢DLSS2。
0的话呢,他做到了,就几乎你不用专门为某一个特定产品,去调你的算法,这一点我说实话我也觉得非常的牛啊,我也不知道他怎么去做的,但是确实就是说啊,就是现现在深度学习的算法基于随着硬件。
它本身就带了很多tensor CORE,就是那个就是那个演绎的这样的一个这个C,这些算算力在哪个在核心上就已经有了之后,实际上真的是越来越强了,所以呢这个算法的话呢,呃其实目前为止的话。
最基础的算法其实有很多人在讨论,包括有些公开论文,但是最新的算法的话,目前好像还没有看到公开的资料,所以我也没办法讲太多,但是呢我们只知道说诶这个算法还挺牛逼的,包括其实全球很多的企业都在竞争这个算法。
我认我个人是非常看好这个方向的,因为我认为未来的渲染的话,不应该是主像素的渲染,因为这个太慢了对吧,我认为基于DEPIN的base的算法的话,其实有很多很了不起的应用,比如现在现在特别火的。
大家知道google的哪个earth做的哪个NERF对吧,这样的一个一个渲染,它能够把整个环境给你重建起来,记几张照片,这个其实也是就是人脑能做的事,也许未来这个深度学习就能做,OK好,言归正传。
我这个回答我们社区的问题的部分,到此言归正传,到我们今天的课程的主体,今天课程讲什么呢,也包括接今天和接下来的两节课,我们讲什么呢,讲再online游戏这个词很难翻译啊,我这个网络游戏是不是更好一点的。
叫网络游戏架构,这个一听呢在我们中国大家一讲网络游戏,大家就觉得这是个坑钱啊,或者什么什么的游戏对吧,所以哪个也叫联网游戏,我觉得嗯好像有点土对吧,那没关系吧,我们就不在这在乎这些细节。
我们就叫做网络游戏的架构。
那么这节课呢我们会讲一些最基础的一些概念,那么网络游戏呢,其实它是相对于单机游戏而言的,就是说其实在早期的游戏,很多时候就是你对这台电脑自己玩就可以了,对吧,玩的很开心。
我们叫single player单人游戏,那么网络游戏的核心是什么呢,就是说让你在任何时候和任何人可以一起玩,就像以前我还记得小时候,我们在街机时代的时候,那我们物理的就会和别人站在一起打游戏对吧。
一边打一边讨论很愉快,包括现在大家有能撑到DS的人联网的时候,也是享受这种快乐,但是呢这个不是一个终极解决方案,终极解法就是只要我有套设备,只要有网络,我就要和任何一个小伙伴能够连在一起,去一起战斗。
那么其实呢就是说网络游戏,它本身呢又很挺复杂的,因为就像我们最早在最开始我在讲games co视频,就跟大家讲过,说,其实做游戏引擎,有一个我们讲的游戏引擎很复杂对吧,但其实呢他那所有的复杂。
只考虑了一个人的情况,如果我们考虑两个人的情况,他这相当于什么呢,就是如果大家理解游戏引擎,是我们在做上帝的活儿,我们在模拟整个universe,整个宇宙,那么它比较麻烦的是什么呢。
就是我看到的宇宙和你看到的宇宙,不是一个世界,哎这个有点像现代物理学的概念了对吧,我们讲平行宇宙,或者说这个这个客观性的言言,哪个讨论,就是说我看到的真实是不是你看到真实,这个问题在我们的游戏引擎里面。
就是很这个切身的感受到了,所以我说游戏引擎的研发者,都都都会成为物理的民科啊,如果大家研究的都研究的比较深的时候,你们一定会变成哪个物理民科,就是说因为我们很深切的很直观地理解到。
就是说100个人联网进入到一个虚拟世界,他们一起战斗的时候,其实他们每个人看到的世界都是不一样的,他们以为彼此看到的是同一个世界,所以说其实怎么样的,再有那么多的复杂的网络的延迟啊。
信息的不完整传递的前提下,我们把这个让彼此之间的世界能够实现同步,保证我们世界之间的发生的事情是一致的,就不要在我的世界里面,这个玻璃瓶是好的,在你的世界里的玻璃瓶已经打碎了对吧。
那你我看到你拿着一个碎的玻璃瓶,起来喝水的时候,我肯定知道说这个世界出了问题,上帝一定我们生活在一定的虚拟世界里面,我记得我小时候看很多电影里面讲,一个人怎么突然意识到我生活在哪个matrix。
就是黑客帝国里面,就是我突然发现天空中出现了巨大的哪个,哪个什么三角形POLYG,或者说我发现了一件不可思议的事情正在发生,这就是我们生活在matrix里面的真实的证据,对不对哈,再讲下去。
就是我们变成这个,哪个什么超自然科学的范畴了,那我们还是回到民科这个范畴,就是说其实啊游戏,网络游戏第一个挑战其实也是最大的挑战,就是说怎么样在那么那么多的universe里面。
我们保持它的一切的事件的一致性,这件事情其实是非常的难,那么第二个难点呢,就是说其实网络世界他最恐怖的一件事情,不仅仅是延迟,而是它它的传输是不可靠的,在这个世界里面其实有很多的。
比如说网络的这个这个丢包啊,或者大大面积delay或者拥塞啊对吧,甚至你会出现断线,你会重连啊,这个大家会觉得很正常,比如说你哪个网游,你觉得诶我掉线了,我回去继续能打,这不是我一个基本的需求嘛。
但其实今天这节课里面我跟大家讲一下,大家就知道这件事情其实挺麻烦的,那我们以前玩过很多网友,我们可以看到,就是对方突然在做一件很逗逼的世界,比如对方突然傻在那了,动不了了对吧。
我们就知道诶这哥们是不是掉线了,那么其实在我们去加一个真正的游戏,online games的这个server或者our client architecture的时候。
这是我们必须要面对和思考的一个问题对吧,上帝彼此之间是不会丢包的,是不会有这个latency的,但是不好意思,在我们的游戏世界里面,我们面对的这个连接其实是经常会丢包。
所以我经常讲说我有时候会羡慕上你就上帝,它是有无限的带宽对吧,而且这个不会丢包,这个还是很牛逼的一件事情,但说不定我一句话说错了,说不定如果我们真的生活在黑客帝国里面,说不定是我们的价格。
是老人家解决了丢包的问题,让我们这些凡人还是感觉不到。
我们生活在一个虚拟的世界好,那么第三个问题呢,其实也是在网络世界里面,大家一个共同面对的问题,就是说大家其实可能没有意识到,就是说其实online games,它本质上是一个巨大的经济系统。
所以的话那么其实在online game里面的话,如何反作弊,反这个就是信息的泄露是一个很重要的责任,就大家意识到就是信我们每个用户,哪个玩家登录到游戏里面,你的个人的IP,你是个人所有的信息。
包括你能不能被人家这个陌生人突然加为好友,或者是别人能hiking你的电脑,或者说去做一些作弊的行为,那么这些的话呢,其实当我们一旦做一个online game的时候,我们就要花很多时间去想这个问题。
为什么呢,如果你做单机游戏对吧,你要hack我们也没有办法,我记得以前哪个啊,我玩单机游戏的时候,我经常会游戏打不过去怎么办,我可以拿一个,就是啊我忘了叫什么哪个软件叫什么来着。
就是你可以找到比如说我的粮食值,或者说我的血量的这个数值,然后呢我可以把那个哪个那个内存地址找到,然后把它数值锁死,这样小怪怎么打我,我都不会掉血,然后我就可以直接强行就过关了对吧。
其实它的原理非常的简单,就是你的啊,你的哪个数值,只要你看见了,你搜三次对吧,他把哪个数字都对上了,就知道是哪个数值,然后再把哪个内存地址给给给给锁死,但是对online game的话。
这件事情就完全不可以接受,你怎么能接受对面来了一个人对吧,你对他一通输出,一通操作,然后对方的血动都没动,你肯定当场就摔键盘,对不对,所以说这其实是online game一个很大的一个挑战。
那么第四个挑战呢其实是多样性,其实大家可能没有意识到,就是我们的online game啊,实际上它面对的设备是非常复杂的,比如说你可能是一个IPAD,可能是个IPHONE对吧。
可能是android base,可能是iOS based,你可能还是PC,那对方可能还是对我们的服务器,可能是一个linux space的服务器,那这么多多样的设备,他们都要能连接在一起。
而且呢都要能跑一样的逻辑,而且online game还有一个很很恐怖的一件事情,这也是啊大家在做游戏引擎的时候,很多说他意识不到的一件事情,就是说我们经常讲的一个词叫热更新对吧。
其实当我们做一个online游戏出去之后,你很多时候会犯很多错误,这个没关系对吧,但是呢大家会说没关系啊,我就推个新版本,但是你想想看,当我的游戏上线之后,很多的小伙伴此时正在玩对吧。
有人正在打的正嗨呢,你怎么办,你其实要有一个办法,就是让大家神不知鬼不觉的把这个bug fixed掉,你要能够快速的去迭代对吧,有的有的时候是游戏的逻辑,有些关键的游戏的一些啊,这个规则都要发生变化。
那这样包括大家想象一下,就现在的网络游戏非常的复杂,大家想象一下,比如说像新世界,像最终幻想对吧,像魔兽这样的世界,它里面有多少的系统,多少的玩法,这么多东西都在这样的一个网络的一个包里面,去彼此连接。
实际上的话这种多样性其实非常的恐怖,所以这也是online,我们在做这个就online gaming的时候很头疼的一个问题,但确实你要去面对的一个问题,那么最后一个的话呢,也就是真正的复杂度吧。
比如说如果我们要构建一个,像头号玩家里的绿洲这样的世界的话,大家想想看,我们要上万的人对吧,在同一个世界里一起去战斗,打枪的打枪拿刀,这个砍小怪的砍小怪,那么这么高的并发度,其实你会发现啊。
就是如果我先两个人在一起连接的,这个操作其实还比较简单,但是我一旦变成了两两百个人对吧,变成了2000个人,变成了2万个人的话,它的复杂度是以N平方在急剧扩张的,而且这里面的话呢。
实际上这些人的网络链接会越来越复杂,所以其实像这种的复杂度的话,实际上是现代哪个online gaming的话,一个非常有挑战的一个价格问题,但我不知道这节课我们有没有时间,本来我们计划有有有计划。
先讲一下这个这个这种架构,但是呢等我们PPT准备完之后,发现我们第一节课就讲了200页,准备了200页的PPT的时候,我们想嗯我们第二节课再看吧对吧,那我们啊。
所以呢这是但确实我我想就是所有有兴趣学games,104的同学的话应该要知道,就是这其实是啊下一代游戏引擎很质,很重要的一个挑战,就是我们觉得这是未来世界,我们一直梦想的那样一个。
games世界的一个一个一个一种起源,我已经受够了,让我进到一个小房间里面,和几个小伙伴在一起的,这个只能你看着我看你的世界,我希望真的有一个让无限进无限出啊,我看到无数的人在一起的那样的一个虚拟世界。
这是我的职业梦想吧,好所以说其实这就通过这几点,我相信同学们就有感觉了,就说诶其实online game还是蛮挑战的,那么好,那今天的话呢,我们就开始了我们online game的第一节课。
这节课呢我们会告诉大家一些最基本的东西,比如说最基础的网络协议是什么,大家会觉得诶,这一趴是不是要教我,这个最基础的叫计算机网络基础啊,大家在大学的时候,有没有学过这么厚的一本,叫计算机网络基础对吧。
那有可能我们会有些内容跟那里面去重的,但确实你会发现当你要做网络游戏的时候,不好意思,大学的时候可以逃课对吧,可以这个这个作业找别人代写,但是你到了自己一些引擎的时候。
那些基础的知识该复习的还是要复习的,那么接下来我给大家讲一些很基本的一些概念,比如时钟怎么去对齐对吧,比如说RPC到底是个什么东西,包括我要做一个网络游戏,我网络拓扑结构到底应该下成什么样子。
那最后呢会给大家讲几个最主流的,就是说网络哪个游戏同步的机制,比如说从快照同步啊,到这个真同步啊,到这个就是状态同步啊对吧,这些都是最basic的,然后呢下一节课会给大家讲一些有意思的东西。
那就是比如说哎听了这么多,其实一个角色在网络环境里面,它的移动怎么同步,大家其实并不知道对吧,这个听上去有点让人沮丧啊,比如说我一个射击打中了,到底没打中,怎么去对齐这件事。
也其实大家并不知道网络有波动的时候,我怎么去补偿对吧,包括一个标准的一个M游戏的网络服务器架构,该怎么去架构,当然了,还有一些更详细的一些概念,比如AI啊,怎么去反作弊,当然了,也许我们有时间。
还可以提一些更有趣的一些东西,所以我们每节课都是这样,就准备之前每节课准备的时间,我们都会觉得哇操这个时间,这个这个这个这个讲啥呢,哪有那么多好讲,当我们开始真的下手去准备的时候。
总发现课程这个时间不够,那么今天的话呢,我们就啊,先把最基础的概念跟同学们讲清楚对吧,这个基础概念也是好像是今天的课程,好像也是一百一百四十页左右吧,但是我争取不要再创造哪个三个小时的记录了。
OK好那我们先给大家讲这个网络的基础的协议,诶,这个很有意思啊,就是说其实首先的话呢,我们传统的节目就要拜神对吧,我们要确实要拜我们的两位大神,就是说是他们最早这个winter和哪个ROBERT。
他们最早去创立的,这个我们的哪个互联网的概念,然后呢他发明了TCPIP协议,人家很厉害,人家一上来就能实现,就是实验室通过电话线,通过卫星的这个所有的链接,当然这是美国军方的一个项目。
所以有的时候我们不得不承认,就是说唉,军事总是能推推进人类科技的发展对吧,那么其实你会说,就有的时候你当我们去研究下去,TCBAP协议的时候,我们还真的很佩服老人家。
就是很早就能够把这几个概念呢分得那么清楚,然后呢,能够让我们能够在上面能很轻松的去做,我们的开发,所以说这确实是我这个就是整个前任,哪个什么前人挖井,后人吃水吧,我们就享受这种快乐。
那么其实的话呢它核心解决的问题是什么呢,就是说我们如何在两台电脑之间传递数据,那么首先的话大家想想,两台电脑之间物理传输是不是特别的粗暴,比如说到底几幅算零,几幅算一呢对吧,我传了0101出去之后。
哪个算偷,哪个算伪呢,对不对,然后的话呢就是这个这些所有的这些信息的话,实际上如果没有这些political的话,实际上我们没有办法穿的,那这个时候呢其实我们就会发现,就是说当我的协议站是很复杂的。
我的硬件连接也是非常有,又有同城电缆电缆对吧,又有无线路由器,又有哪个就是网线光纤,那其实这里面,如果我们不做一个特殊的处理的话,你会发现我们要处理很多很多很奇怪的情况,但是呢。
同学们如果自己去学一些简单的T和电脑知识,我们知道说哎很多事情不需要我们去发愁了,因为我们在中间加了一层中间的layer,这层layer的话,其实把所有的硬件的这种复杂性全部隔绝掉,所以大家各种协议。
只是直接往里面去写东西对吧,然后呢由他们来负责各种分发,大家如果有机会啊,去到哪个机房去啊,我我我因为我工作的原因嘛,我经常去机房嘛,我每次对我们的IT的同学就特别的崇拜。
因为你当你看到哪个一个一个路由器,就真正专业级的路由器,那分出来那些线的时候,你会觉得我的天呐,就是跟大家讲一下,就机房里面盘哪个电缆线的,哪个就是哪个哪个cable的,哪个人都是一门技术活。
它11cm的线都要有编号,然后接上这么粗的这个电缆柱,这样走起来很足的电缆线,所以说你会发现在这里面无数的比特在交换,无数的比特在算法,但是呢,今天当我们去写一个网络的这个程序的时候。
我们其实根本不需要去在乎这样的一些复杂度,对吧,这就是要感谢我们的前任,把这个分成分的非常好,所以这里面的话呢就是要感谢一下我们的前人,著名的OSI模型,对不对,那么其实这个模型的话呢。
就是我们最经典的这个网络的七层模型,一层一层的下来,那看了那么多,对不对,从最最基础的physics层到哪个数据连接层,到网络层,到这个传输层对吧,到网上绘画层,到我们的这个就是表达层和我们的应用层。
实际上我们一般用不到那么深,我们大概一般都在应用层,各种鬼混就完事了,然后呢接下来就往上传数据,但是这种分层结构这种思想其实非常的有用,而且我待会儿后面还跟他讲的,就是我们在定义很多协议的时候。
其实我们需要对这东西有一些基础的理解,比如说为什么这件事情很重要,举个例子,比如说你要做一个应用,假设你做一个啊,比如说啊哪个,比如说CDN对吧,就是一个给人家提供各种下载服务的东西。
你需要对着七层协议非常理解,那么你会发现,这七层里面有大量的冗余的数据拷贝,对不对,你可以直接对这个协议底层进行优化对吧,那这当然这是一些非常高端的一些东西了,那么在往我们做游戏的时候呢。
有的时候我们不用那么深,但是不代表,在未来最前沿的一些产品研发的时候,我们有可能对这个协议都要进行优化好,那么其实呢,对于大部分的这个游戏引擎开发者来讲的话,我们不需要那么复杂。
我们说OK我们用一个socket编程,对吧,socket多方便,对不对,你只要提供一个IP地址,提供一个就是说哪个port端口号,我就可以跟对方建立我想要的链接了,但其实你们仔细看所有的网游。
它本质上你下载好你的客户端,你怎么去找到人家的服务器呢,实际上是在客户端你就写死了,说你就到这个IP地址,你就到哪个port已经在连到我的服务器,当然了,这里面没有那么简单,因为如果就是那么简单的话。
比如说我用最简单的一个DDOS攻击,就可以把一个游戏给黑掉,但其实呢大家在网络游戏啊,以前至少最怕的一个东西是什么,就是被别人恶意攻击,就是啊因为有你,因为你的服务器地址必须必须是开放的嘛。
如果他本身不具有一定的,就是说这个这个抗DDOS的能力的话,其实你可以很容易地写一个东西,把一个比如说别人在运行的好好的游戏,给他攻击掉,但现代网游的话呢,一般会做了很多的相应的处理。
就是没有那么简单了,同学们标示啊,这个是违法的,好不好,哈哈这个所有这个你觉得有趣的事情,很可能就是旁边就是有东西在等着你,所以我只是跟大家讲一个这样的一个,技术原理啊,这个不好意思,教小朋友学坏了啊。
然后呢,其实socket的话呢本身也是比较简单,很明确的对吧,就是说它实际上就是说,你通过这样的一个简单的接口,你就可以跟另外一台机器间的连接,然后呢你确定好你的协议。
就可以持续不断的往对方去传输你这样的东西,那这里面的话,我想给大家分享一个很有意思的东西,就是说其实在socket建立的时候,大家会说哎我是到底是IPV4,IPV6对吧。
我到底走的是TCB还是UTB协议,对这些东西大家的标准哪个选项,我这边讲有意思的东西,就是我们在中国,我们做很多在线应用的时候,我们一般用的是IPV4G多一点,当然大家如果注意到。
就是如果你要做一个真正的通用游戏引擎的话,我会建议大家一定要考虑IPV6,因为什么呢,因为在全球有很多国家,我如果没记错的话,好像是德国吧,我记得德国就是其中一个,就是他们已经大面积的在使用IPV6了。
所以你你的做了一个服务器的话,如果你不进入FPV6的话,有可能很多用户连接不上你的服务器,所以说你要做一个提供服务器的游戏,引擎的时候,A不好意思,这就是你要考虑的内容了,对吧好,那么其实这里面的话。
当我们有了socket之后,我们就要理解什么叫大名鼎鼎的游戏了啊,有那个哪个哪个pole了,就协议了,那最著名的就是TCP协议了,TCP协议其实是一个最最经典的一个,互联网的协议。
可以说互联网上传递的绝大部分信息的话,其实都通过TCP来去传输,大家怎么去理解TCP协议呢,就具体的细节我就不展开了对吧,那么TCP协议呢它首先是一个就是通过三次握手,建立了一个牢靠的这样的一个连接。
所以TCP连接是一个比较稳的,那么另外一个的话呢,就是说它的确保我的发的包一个一个一次一次,它是有顺序的,就是前面的包不会和后面的包去冲突,另外一个呢TCP呢还有一个很厉害的属性,就是什么呢。
它会进行流量控制,也就是说当网络发生拥塞啊,或者各种阻塞的时候,它会自动的降低我发布的效率,所以说这也是为什么很多啊,比如说网关配的策略的时候,对TCP都相对比较友好,如果这个是这个就这么说吧。
如果互联网上跑的都不是TCP协议的话,很可能今天我们大家用的网络都是非常的这个,拥塞不堪,因为每一个人都是玩着命的给别人发消息对吧,就跟我们讲这个,比如大家每个人都是玩命的发电邮,反正呢也不用管你。
邮票也不花钱,结果你很容易就会把这个就是说这个一个邮,邮件服务器给轰炸掉对吧,以前我们知道有垃圾邮件,其实TCB这一点的话,它其实是有流量控制的,说如果每天这个网,我们的网络上下行链路传输的量。
超过了我的上限的时候,我会相相应的进行一些控制,那么PCB的包头呢比较长了,它可以达到20个BT,就20个字节那么大,其实还是有点有点有点有点重的,但是的话呢它一旦建立链接之后呢。
它就会持续不断地传传这个信息,那么它能够保证这个信息的一致性,其实TCB啊,它的核心原理实际上就是一个叫rich Mission,Mechanism,就是非常的简单。
就是这里面它实际上就当我的任何一个接收者,收到一个信息的时候,诶我给我的3DER发一个ACOLOGMENT的,就是一个告知,就A4简称ACK,那么我的center呢只有收到了ACK之后。
我在持续的网上发报,当然这是最基本的原理啊,其实在后面我们会讲到一些更多的细节,但是大家知道这个基本原理就可以了,就是说如果我却没有得到确认,说我的内容被你收到之后,那我就会持续给你发对吧,这个当然了。
这个本身也会导致一些网络拥塞,那另外一个的话呢,就是说其实TCP呢它有一个很有趣的叫做,这个就是拥塞控制,它,实际上就刚才刚才,大家看到我们塞的这么多包啊,它不是真的一个一个散,它是一次一次一批批散的。
它是有个有个窗口的,但是呢他一开始窗口很小,然后呢我就开始传传传,如果我每次都很顺利传过去,很快我就收到别人的ACLACK,就ACCLASSMAN的话呢,我说ok fine。
那我就把我的窗口变得更大一点,我就一次性多传一些对吧,但是呢当我一旦发现我的这个ACCLASSM的,这个包出现丢包的时候,哎我就开始把我的哪个窗口往下滑,就我一次就少散的一点。
这样的话当我们去大家想象一下,如果在一个不是特别稳定的网络环境下,比如说有可能是因为网络真的有丢包了,或者说他只是因为波动对吧,大家知道网络其实是会经常波动的,为什么呢,大家想想看你们家小区的网络。
当你们家小区现在有部很火的这个电影,哪个比如说大电影网络网,大电影上线的时候,你会发现你们小区的网络就一定很差,为什么大家所有人都在抢哪个贷款,那么同样在一个不稳定的一个公网上的情况下。
其实TCB的链接给你看到的整个带宽的波动,就像这张图这样,就是诶一会儿快,一会儿慢,一会儿快,一会儿慢,所以当我们做一些应用的时候,特别是对游戏这种对时间特别敏感的时候,我们就会觉得有点难受对吧。
这是但是呢它实际上也是TCP,很多时候导致大家的延迟的一个原因,但同时又是我们互联网上就是能够保证,就是互联网没有炸掉的一个很大的一个保障,因为美如果每个人都遵守这个TCP协议的话。
实际上我们有一个动态的,就相当于就像就像马路上开车,你发现哪个这个车前面车很多的时候,你可以自觉地把速度减慢对吧,你会自觉的不去挤上哪个高架,那个高架最终还是能通行的,如果所有人都不管不顾的往上冲的话。
那高架很快就堵牢了,堵牢了之后,大家全都走不了,所以说这我我要讲的就是TCB的这个,congestion control的环,实际上对互联网是落立功了了,但这件事情的话呢,唉为什么在讲一个游戏引擎课上。
会讲的那么那么细呢,因为这东西跟我们的关系还是蛮大的,好,另外一个的话呢就是要讲到这个TCP的问题的话,就要讲到另外一个大名鼎鼎的协议了,就UDP了对吧,UDP哪个老哥其实非常有意思。
其实他实际上也是TCP的发明者之一,但是他在10年之后吧,就发明了这个就是UDP这个协议,它本质上哪个端端端的协议,大家想想TCP也很万能对吧,它能够在整个哪个互联网上去广播啊,去找东西。
但是呢UDP他的想法很单纯,就是如果我只有两个设备,我们彼此之间传数据怎么传,那我肯定希望越简单越好,对不对,我也不要那么多复杂的哪个约束了对吧,我也不要求你的order有什么东西,那么其实呢。
所以这个老哥就发明了UDP这个协议,其实UDP这个协议呢,其实我个人还是蛮非常喜欢的,就是说第一个呢,他就是说不需要建立长时间的链接,就是我们不要没事握手对吧,我看你顺眼,我就直接发给你了,你爱收不收。
那是你的事对吧,第二个的话呢,就是A我其实也不是要求你一定要稳定,然后呢也不要求你保证一定order,就像你发电影一样的,我我你这个邮件早收到这个几分钟,晚收到几分钟也死不了人对吧,那我就不停的这个发。
我就发给你就行了,第二个的话呢,我没有这个flow control,也没有这个congestion control,就是流量控制,我也不管,这就是UTP,实际上是个很祸害的一个一个一个协议。
就是说呃怎么说呢,就是如果你想用UDP干坏事的话,UDP其实很容易干坏事,就是他反正也没有流量控制,你就往上塞就好了,那么因为他的协议非常的简单啊,所以UDP它的包头就会比较的轻,如果我没记错。
应该只有四个字,四个BT,就是说四个字节32位,我就能存一个UTB的包头,这样看看是不是诶,我的包头就比TCP轻了五倍左右,所以这是UDP一个很大的一个优势,那么好,那所以呢其实呢在现代游戏里面。
你可以发现就是说不同的游戏他的选择不同,比如说你看像哪个我们的炉石选用的就是TCP,对吧,打打打炉石用于TCP,然后呢比如像守望啊,像其他的游戏,我们用的是什么呢,我们用的是TCUDP。
但实际上呢这两个协议诶真真实的,在游戏中的话,举个例子啊,比如说一个大型的MV里面,我们到底选哪个呢,这里面我只能分享一下我个人的一些经验,我们没有不一定按照这个课件去读,给他他课件的东西。
大家可以读一读,这些话说的也是有道理的,但是的话呢实际上我的理解就是说,比如像你打炉石这种对吧,你对延迟,比如说0。2秒,0。3秒,你真的那么介意吗,好像没有,那么介意对吧。
对于那种时间并没有那么特别敏感的操作,我们会选择用TCP协议比较好一点对吧,它它连接是稳定的,那么但是的话呢,对于比如说快速的这种射击游戏啊,我要响应特别特别快啊,尤其是在这种不稳定的网络的情况下。
特别公网上的话,其实大家现在越来越多的会有UTB这个协议,因为它是非常responsive的,反应比较快,但是真正的对一个大型的,就是这个这个这个mo来讲的话,实际上它用的一般都不是单一的协议。
他会用组合协议,比如说我有的时候用TCP协议来进行签名认证,确定你的登录啊,建立你的账号链接啊,而且这个这个有的时候我们心跳也会用,就是哪个心跳包也会用TCP一直给你维持住,但有的时候我们也用UDP。
但是呢游戏真的战斗啊,进入到这个世界的时候,我又会UDP,但是呢说不定我到了聊聊天啊,我到了那个什么别的,比如说邮件啊,我可能又走了哪个TCB的通道,其实我们一般会看哪个通道更合适,我就走哪个通道。
所以简单来讲的话呢,就是这个又回到了我们104的这个精神,就是说游戏引擎,实际上它是一个没有任何的教条主义的这样,一个一个一个工程科学,所以一切的一切的这个,这个就是说人类智慧的成果。
对我们来讲都是工具,我们更重要的是要构建那样的一个黑客帝国,这样的世界,所以的话呢对每个技术,我们都要有一个比较清晰的定位和理解好,这就是一个最基本的哪个网络的协议,哎如果故事讲到这儿。
我们就结束了对吧,大家知道了TCPUDB,那我们就凭着自己的感觉去用吧,但实际上的话呢在现代游戏里面,我们很多时候并不会直接的用原生态的引擎,我们会对啊,原生态的这个就是说协议,我们会对协议进行改造。
那么这个为什么要改造呢,其实这个问题其实在前面已经讲的比较清楚了,就是大家没有发现就TCP的问题是什么,哎呀这个老人家磨磨磨唧唧的对吧,它非常的好,很很很稳健,很可靠。
但是呢它的带宽一会儿上一会儿下对吧,而且呢前面的消息只要没有收到确认,后面的消息似乎不发,其实有的时候打游戏的时候,你有的时候有些消息丢了不就丢了嘛,无所谓,对不对,我我现在我这个输出。
我这个操作我就特别想打出去对吧,我一通操作,把对方就想这个直接给哪个血给磨没了,对不对,你这时候不让我发出去,就是因为我前面一个移动这个消息没有传过去,那我觉得作为玩家是不是很难受对吧,那那肯定TCB。
这个时候大家就会觉得有点难受了,那怎么办呢,哎我们用UDPUT意识很好,他非常fast,而且它能满足我的要求,就是今天我打出了一个输出,我前面一个向左移动,我一个连跳没传过去,拉倒无所谓对吧。
但是的话UDP实际上是真的是非常的不reliable,也是某种意义上来讲的话,我们根本不知道这老哥到底有没有传到,对吧,那那这个问题就比较麻烦了,对不对,你发出去的包,这个这个这个打出去就不管了。
对不对,那我服务器客户端之间最起码的信任都会没有,所以其实这个时候就会有聪明人说哎,我能不能把两个学期的优点给结合起来,这其实就是在现代游戏引擎里面,就是这也是我会推荐大家,如果你们在做自己的游戏引擎。
特别是做online联名的时候,我会非常推荐大家,就是要么去采用第三方的,让我们自己定制一个啊,基于UDP的一个可靠链接的协议,这件事情其实啊难度并不像大家想的那么大。
而且这里面的很多很有趣的一些数学原理,大家也可以在里面去自己应用,所以呢这就是我们104课要讲的就是,A如何构建一个可靠的UDP连接,那么就是说这里面的话呢,其实前面已经讲的比较清楚了。
就是说为什么定制一个自己定这个协议,这么重要的,其实我们去看哪个游戏的服务器开发,和网络的服务器,就是标准的web服器开发其实有很大的区别,游戏你会发现,比如说我们要总是要保持活着的链接。
这个看听上去有点像TCP对吧,然后呢,我们最好呢要保证这些消息传递,还是有一定order的,我们真的乱序,其实我们也受不了对吧,我们有些动作,比如说我要先给自己喝个草药对吧。
然后我的我的我的这个这个魔法之上了,然后我再去打一个技能对吧,我的魔魔法就够了,我的蓝够了,那这个还是有顺序的,对不对,那么所以呢我们还是要保持一定的这个order,在里面。
这两个需求听上去好像挺7CP的对吧,但是的话呢我们又要非常高的,这个就是responsive,非常快,而且最好没有延迟,还有一个的话呢就是经常我们要群发对吧,就像我们讲了,这个上帝如何能够实现多个宇宙。
multiverse之间的信息同步,是不是我经常要send all对吧,就是这个服务器说收到一件事,我马上就要send or send send,所以我经常有broadcasting这样的需求。
那么其实这两个呢其实又很符合UDB的特征,所以呢我们就很贪心地说,我们能不能定制一个协议,把这两大协议的这个优点都结合在一起,那么实际上的话这里面先讲一个基本的概念,就是说哪个前面其实前面已经提到了。
OLOGAN的ACK对吧,就是说我收到一个包,我给你确认收收过了,其实ACK呢还有一个他的孪生兄弟,叫n AC k neck,就是说negative AC k什么意思呢,就是说我除了能告诉你说。
我收到了某某的包之外,我还能告诉你说哎什么包我没收到对吧,那这样的话是不是一样也有信息量传递下来,其实你会发现做网络很多时候,我觉得跟信息学的一些技术理论很接近,就是我们在一个彼此不可靠的链接下。
怎么样建立一个可靠的彼此信任的通讯,它本质还是这么个原理,其实我们在人类古代大家想想看啊,因为我以前很喜欢读历史嘛,就很有意思,你会发现古代,比如说A地到BD两个指挥官之间,他们要协同作战。
但是他们知道我传递的所有的这个传信的,这样的一个通讯者,他们都有可能会半路上被人截杀对吧,而且也有可能被人compromise,就是被人俘获并且叛变,然后呢,而且呢这个中间会有个latency。
就有很多的延迟,对不对对吧,那么好,那怎么样的,在两支协同作战的军队之间,建立这种可靠的通讯,其实也是一个非常有意思的一个问题,这个问题其实跟我们在网络的问题上,解决的问题一模一样,那么另外一个的话呢。
就是我们要加入这个序列号,那这个其实大家知道,我给哪个包哪个编号对吧,那么呢还有一个time out,就是说诶过期的时间就有些时间时间过长了,我们就不理他了,其实当我们去基于UDP。
构建一个相对稳定的这样的链接的时候呢,你又要用到这些概念,这些概念呢实际上啊你说他陌生吗,他其实不陌生,大家如果去学习TCP的真正的底层实现的时候,你会发现这些就是我们的老朋友对吧。
那首先的话呢这里面的话要提出一个概念,就是这个ARQ对吧,就是说自动的这个回复的这个哪个重复的要求,它实际上是个简单的例子,就是说当我建立一个就是网络链接传播的时候,如果我丢包了,或者我没有收到的时候。
我能够有个方法能告诉你,你能自动给我传发包,所以我所有的算法都要实现LRQ这样的效果,那LUQ呢有很多算法,所以呢我们在这里跟大家简单讲几个基础,基础概念,那么第一种概念呢。
就是说哎我们要有一个叫sliding window pole,就是滑动窗口协议,就是说当我的包体啊,一大块很多很多的数据我要传输的时候,其实我有个窗口的,我一次性会把窗口你的数据全传过去。
这个时候当我收到了诶,是那个接收方发返回来的ACK包的时候,比如说我收到了第2号包回来的时候,我就知道了,哪个345就是3号包啊,哪个2012已经传传输出到位了,因为我只要顺序的确认嘛。
那我接下来就把3456传过去,那因为三我已经传了,我就把456传传过去对吧,直到我收到了后续的这个ACK这个包,过来之后,我这个窗口游戏需求也往下滑,这个原理是不是非常的简单对吧。
那么这里面的话呢我们就有很多策略了,比如说最简单stop and the weight a r q,什么意思呢,就是说我这个窗口是三零,我每个包放完之后,我都在都要等你的这个确认了,包收到,我再往上走。
那这个的话呢,这个方法其实是最古典的一个方法,这个方法从来就没有用过,为什么呢,因为它特别笨,你想想看,比如说我有很多的上行带宽对吧,但是呢我传完一个包,传完之后,我就等等等。
网络的延迟至少一个来一来一回的话,一两百毫秒至少过去对吧,那这一两百毫秒的话,我们所有人都在等着呢,所以这个带宽其实没有被充分的利用,所以呢这个呢是一个最简单的方法。
那么还有一个就是go back and aq,什么意思,就是其实刚才那个窗口里面,就是说如果我发现我一个包丢了之后,我其实只是把一个窗口,你的包再重新传一遍,那这个的话呢。
策略呢其实是一个非常实用的一个策略,实际上在我们的这个就是,如果我们做自己的reliable,这个UDP的协议的时候,诶,我会推荐大家用这个策略。
那么更有意思的就是selective repeat a r q,这个地方的话,其实它是用了哪个negative l q l ark,就是说我告诉你是说什么包我没有收到,你就继续往下传,但是我告诉你说。
比如说我哪个包我丢了,比如在这里面的话,2号包丢了,那好那你把2号包再给我再传一次就好了,那这样的话呢其实它的链接可以更稳定,而且呢也能节约一些不必要,不必要的哪个贷款的浪费。
但是他有个额外的那个就是哪个a logy的类型,就是NARK,就是告诉你说这个包我没有收到,这里的算法讲讲起来的细节其实是非常的多,但这个呢不是我们这节课的重点,其实我我想跟大家讲的,就是说。
同学们如果要去构建一个自己的,就是for游戏引擎的这样的一个网络,底层的时候呢,确实要非常认真的去考虑,你下面要构建一层,基于UDP的一个可靠的网络连接,但这种东西的话,其实现在啊有很多的开源库。
也在解决类似的问题,就是说他能够就UTB给你构建一个唉,你要保证顺序一致啊,你要保证这个非常可靠啊,你要保证哪个非常低延迟啊,这样的一个一个一个一个包装,所以我觉得UDP是个很好的协议。
就是它提供了一个很基础的构建模块,上面的策略完全用我们自己去配置,那么其实的话呢就是说还有一点就是说诶,其实在UTP传输的时候呢,我们还经常会遇到一个问题,就是丢包对吧,UTP说了丢包我不管对吧。
我只管发出去,但是他可以不管,我们得管,那这个怎么办,诶,这里面有一个很重要的策略,就是这个forward error correction,这这个策略的话呢,也是我们在构建的底层会用到的东西。
就是说如果你丢包了之后,我能不能说在丢包率,比如说只有5%啊,10%的时候,我不要没事就让你重传一遍,大家知道重传这个事情很麻烦对吧,我第一个我要等你的ACK收到,收到之后呢。
我然后再把那个老早以前的包拿来,给你重传一遍,而且如果是一个滑动窗口的方式,其实我后面的所有的包都得卡在那儿,对不对,所以说其实如果有一个方式是说你的包丢了,我也不管我继续往前走的话,那是不是岂不美哉。
所以的话呢,其实聪明的人类就想出了很多方法说诶,我能不能有一个方法,就是说我收到了包,我知道这个数据丢了,但是我一样能够把你正确的数据给找到,这里面的话呢就有一个非常有意思的策略了,我们叫做。
我们以前在学这个计算机体系结构的时候,经常讲的一句话,叫什么叫空间换时间对吧,那我我就是用额外的数据传输量,来解决这个问题,那大家说怎么办,我把数据再传一遍,对不对,我哪个数据传两遍行不行啊。
当然可以了,但这个方法实在太笨了对吧,我们还是要用一点稍微高级的方法,其实呢这个其实是VC,这个这个算法就是for的哪个哪个error correction,哪个算法实际上比大家想象的要简单。
这里面我给大家介绍两种很简单的算法,第一种方法就是什么呢,抑或降盐味的算法对吧,第二种呢就算哪个介绍哪个啊,就是SOLOMON的一个算法,Solomon codec。
这也是计算机信息里面最经典的一个算法吧,OK那首先讲异或吧,抑或其实大家知道什么叫异或运算,对不对,就是说当给你两个beat,那么他们如果是一样的话,那么它的异或值就是零,就表示你们俩一通我不喜欢对吧。
你们两个是不一样,比如说A是零,B是一,或者是A是一,B是零,他们两个就是哪个异或运算结果就是一对吧,如果两边都是一异或运算,120这个算法提上去哎,就那么回事,对不对。
好像我们在学计算机组成原理的时候,我们经常会用到这个这个算法,那异或运算它巧妙在什么地方呢,哎大家看看我们这里哪个有意思的东西,就是当我给你数据,假设有ABCD4个数据。
我把ABCD的异化算出来的结果是E的话,你得到了这个值呢,其实就是一个校验位,这个校验位呢不仅可以校验你这个值,对不对,他其实也不算校验嘛,但是他其实确实可以教研,但是他更厉害的是什么呢。
就是当你的ABCD中间任何一个丢掉的话,我可以把你的剩下的地方,和我的E在一起做异或运算,得到的结果就是你原来的值,哎这个数学让大家可以自己推演一下,其实很简单,但是呢这个定理是可以被证明的。
他一定对的,但是大家会问说,那如果E自己被丢了怎么办,那也无所谓了,反正我的信息是ABCD嘛对吧,E丢了就丢了,拉倒了这个东西其实是什么呢,就是大家哪个如果学过哪个硬盘的,存储阵列的时候。
大家知道有个概念叫red five,对不对,就是哪个rate对吧,就是我们的存储,哪个磁盘存储的哪个数据的冗余,其实就是这个算法对吧,就是我五块硬盘,四块硬盘存数据,一块硬盘存它的异或值。
这样的话这四块里面其实五块里面坏了,任何一个哎,我都能迅速的把这个数据pick up对吧,这其实就是这个道理,所以其实这个简单的原理的话呢,就可以用在我们的计算机里面,所以这里面大家可以算个概率。
就是说如果我的丢包率大概只有12%,或者是5%的时候,其实你这个预算在这的话,你可以极大的减少,你的这个就是重发的这个概率,但是如果你的丢包率接近于10%,到20的时候,诶。
你会发现哎呀你又浪费了我20%的贷款,其实很多时候你还是救不了我的命对吧,但这里面要有一个比较严格的一个概率运算了,这里面我就不展开了,那么这个方法呢其实还是挺不错的。
那有没有就是说诶我可以同时丢两个数据,甚至更多的数据我都不会丢掉的,算法呢,这里面的话就要讲著名的这个RESOLOMON的这个,codex算法,这个其实是一个计算机的哪个高级。
哪个就是体系结构里面一个很重要的一个算法,这个算法其实不止用在我们的网络重输,他的简单,他的思想其实是非常的巧妙,就是说我对于我任何一个codex的信息,比如说D我去构建一个。
就是说哪个王尔蒙德的这个这个这个矩阵,这个矩阵的特点是什么呢,就是说我的上半部分是一个对角阵对吧,全是一下半部分呢,这个是我构造出来的哪个矩阵,它的特点是什么呢,就是说我从中间的任何任意抽调。
比如说若干行,这13行哎,比如说我我玩玩延拖了三行,我中间任意抽到三行,这个矩阵都是可逆的,那这个可逆性为什么这么重要呢,大家看这个情况啊,比如说我现在把这个矩阵构建好了之后。
比如说我构建了一个矩阵叫B,然后呢我把这个信息D跟这个B进行一个乘法,那我得到了我这个我codex出来的这个信息记,大家发现没有,记得上部分跟原来的数据是一模一样的对,但下部分好像出现了一些荣誉的信息。
比如说我现在呃五个信息里面我加了三个荣誉,对吧,好,这个时候假设我非常不幸的在传输的过程中,我丢了大概啊123,我丢了三个包对吧,这是最最坏的情况,就是啊我八个包中我丢了三个,这个丢包率接近于百分之。
应该就快要接近30%了吧,哦不止了,30%到35%左右了,好这种情况下,我能不能把信息给它恢复,大家看这个时候呢,你会发现这个矩阵运算是这样的,就是实际上你把你所有丢掉的哪个信息的哪个。
哪个哪个哪个那行啊,那那应该是那一行对,把它全部移掉,你就可以从B矩阵收缩成B1撇矩阵,而且这个BP矩阵的话呢,它一定是一个就是一个一个一个一个一个,就是长宽一样的这个矩阵。
然后呢他实际上你现在得到了质量,不是相当于说B1撇乘上了原始信息,然后得到了你现在拿到这个信息吗,那这里面就有一个非常简单的一个数学变化了,就是说如果这件事情成立的话,我把B1撇给他求个逆对吧。
那我让他去乘上这个我拿到的这个信息的话,其实它就等于这个,我就等于说把原来的数据给重建出来了,这里面其实本质上原因是什么呢,就是这个矩阵呢它本身你任意抽调三行,它都能够得到一个可逆的矩阵。
所以呢它这就意味着什么,意味着你的信息其实是没有丢掉的,所以你通过一部数学的逆运算,就可以把原来的信息给重建出来,所以这个算法的话呢,实际上是一个非常啊无proven,就是已经被证明了非常好的一个算法。
而且实际上在网络传输中,我们用的其实非常多,包括就是如果大家想建议,建立一个鲁棒的这种网络链接,打个比方吧,比如说你大家做的是手游对吧,那么在手游的话,移动端下的话。
这个网络链接其实很多时候都是不稳定的,那么用这个RESOLOMON的这个算法的话呢,实际上是能够非常好的帮助你解决丢包的问题,因为有的时候在手机上丢包率,甚至可以超过10%到20都有可能。
因为你家里加了又有WIFI,又是手游对吧,这个就很麻烦,所以的话呢我们不能老是要断线重连,老是在等新的包,因为我每一次等于他的ACK的话,200ms就过去了,那其实这个游戏就没法玩了。
所以说这个东西其实不是,大家会觉得这里面数学是不是很抽象,其实数学非常的简单,就是你构造一个矩阵,中间任意抽掉他的哪个哪个若干行之后,诶,他还是一个可逆的矩阵,这样的话我拿到的信息之后。
只要乘上哪个抽掉对应行的哪个矩阵的逆,我就可以把原始的信心恢复了,其实就这么个简单的道理,但是的话呢它实际上真的是非常的有用,所以其实啊今天我们讲,就是说,我们要构建一个自己的可靠的基础链接的话。
实际上我个人的理解就是,你只要对OORQ的基本算法有所理解对吧,你可以选择性的使用说诶,我用这个就是哪个slide windows的方法,去一个PO去传输我的数据对吧。
我确定我的这个就是说resin的策略,RETRANSMIT的策略,其实RETR视频策略其实完全可以,自己很多的小小技巧可以去定制,然后呢我再加上一定的FEQ的这个算法。
这样保证即使在一定的丢包率的情况下,我这个包体还是能正确的收到,这样的确保我的ACK的话总是成功,尽量的成功,不要老是丢掉,那么当这两个东西在自由组合的时候,其实啊你就可以定制自己的独立的UTB策略。
所以大家会发现,就是说在很多的游戏引擎底层的网络链接,假设它是用UDP包装过的话,它一般当你建立链接的时候,一般我们会建立很多链接,就是说我们的客户端和服务器,会建立各种各样的链接。
然后呢诶你可以选择策略,比如有些东西我就是要求他高稳定性对吧,但我对延迟并不是那么敏感,那我可能诶策略中会向稳定性那边切清,哪个轻的更多一点,这个地方的话呢,其实我要求的是low latency。
就是我要响应特别快,但是丢几个包问题不大,比如说玩家那种左移右移的那种操作对吧,丢了两个也无所谓,对不对,那没关系,那我就可以追求哪个,就是说highly response对吧。
对于这种就是说他的哪个就是丢包啊,这些东西我并没有那么敏感,所以其实这就意味着,就是说当我们把这个没有用包装好的TCP协议,而是要用自己的UDP自己去组合的时候,你会发现特别适合游戏的这种复杂的情况。
我可以自由组合各种我们想要的这种体验对吧,这个定制化DIY总是开开心的,所以讲了这么多,其实跟大家讲的就是,我们作为一个网游的最基础的东西,首先你怎么建立一个网络链接,大家发现没意思。
就是说作为一个引擎,连底层的链,底层的哪个传输协议都需要我们自己定义定制,确实是这样,如果大家如果做一些更复杂的这个,这个网络游戏的话,甚至有可能哪个连底层的协议账我们都要去改,当然哪个就更更复杂了。
我们今天就不展开了,那么好了,有了这样的东西的时候,诶,我们是不是就开始可以写我们心爱的小网游了,对不对,我们可以做个对战游戏了对吧,大家都很想做对战游戏,诶,这里面有一个大家以前可能根本想不到的东西。
就是说我们的在做网游之前,在做对战游戏之前,第一件事情是什么,我们得把彼此的时钟对准,大家可能没有想到对吧,为什么要做对战游戏,为什么要把时钟对准呢,因为很简单,就是我现在说我这个player。
这个玩家A说,我在这个13秒零五打了一个一发子弹对吧,普莱尔B说我在13秒零六做了一把躲闪动作,我到底算是这个躲过了还是没躲过的呢,如果你们彼此的时间是没有对准的时候。
你们觉得是不是大家彼此之间都不再说什么了,对吧,所以其实啊就这就是网络这个世界非常复杂的,就是还是哪个我用哪个MTUNIVERSE,就是多重宇宙的概念,就是在不同的宇宙里面,我们的时间都是不同步的。
你看明天科民科又起作用了对吧,所以说相对论讲的所有东西,在我们游戏里面都会遇到,就是说每一个人的世界坐标系都是相,都是叫做什么,就都是相对坐标系,只是以以自我为中心的,那么多个universe之间的话。
他们第一步就要把时钟序对准,那么好时钟怎么去对准呢,那么这里面就要理解,在网络上我们产生各种各样的问题,第一个呢大家知道有个概念叫RTT,叫round trip time。
就是说我从我发一个包给对方多久时间,我能收到一个回报,诶,大家在哪个就是网络操作系统的时候,以前经常学的一个值叫什么叫ping值对吧,我们经常没事ping一下别人,然后收到别人的这个这个叫TTL对吧。
这回回来一个值,那么RTT和ping值到底有什么区别呢,其实他们两个实际上非常的接近,但是呢如果你严格的死抠的话呢,是有那么一丢丢的区别,就是说ping值更底层一点,因为它是你的这个网络协议。
这OS更底层可能是在传输层那一层,可能更下面一点,他们去做的所有的自我的检测,他们也通过上面的这个应用层和哪个表达层,但RTT呢很多时候是我们应用层自己写的,比如说我们一个游戏对吧。
我的客户端发一个包过去给服务器,服务器多久回给我,我就能测试我的RTT,那么我可以就可以知道现在的网络的延迟情况,和他的latency,但是呢其实在游戏引擎这里面的话呢。
很多时候你这两个字不用区分的那么的严格,而且对我们更有用的可能是RTT多一点,怎么去对视,其实这个问题啊是一个非常will sa problem,也不叫WILSON,是很重要的一个问题,大家想想看。
其实这需要对时间这件事情啊,在全世界,这是一个极为关键的应用,为什么你可以比如说我们大家经常用的GPS对吧,GPS的本质原理是什么呢,就是在天上飞了24颗卫星,每个上面都装了极其准确的电子钟。
然后呢你要你的GPS接收装置,你需要跟这些原子钟去收它的信号,然后他彼此之间呢是要对时的,然后呢你要有一个很精准的就是时间的相位差,你用三角定位法,就是你能算出你和他们彼此之间,距离的差是多少。
这个时候你就可以算出我在地球表面的位置,所以其实我们在很多的系统,以免都要去定时的问题,但定时问题它最难就对时间这个问题对对,世界问题最难的一件事情是什么呢,就是说任何的信息传输是不能超过什么。
不能超过光速的,对不对,当我北京的一个中说,现在是北京时间七点整,你拿你的表掏出来跟人家对的时候,我且不说你的反应速度,各种各样的速度吧,那你就这个北京,这个这个从北京时间七点整传到你这来的时候。
你已经过了,大概可能是零点几百毫秒了对吧,所以说其实啊当然你会觉得我们在现实生活中,这个钟的话有这误差问题不是很大,但是对于这种GPS这种精密仪器来讲,这个影响是非常非常大的。
所以呢其实有人专门研究这个东西,那么最经典的一个算法叫什么呢,叫NTP叫network time ple,就是哪个网络的时间的哪个协议,这个协议其实呢非常的简单,给大家讲一下。
就是怎么去理解这个对视问题呢,哎这里面再讲个概念,就是对时,它很多时候是一层层的,它有个叫stratus,就是就像地层一样的,但这个就比较比较比较比较比较比较形而上了。
就比如说我们有一个北京紫金山天文台啊,南京紫金山天文台最精准的一个天文钟对吧,那我们一层层的去对,一般来讲你好,原则上讲是这个据说超过了15层之后,这个这个钟就对的不准了,但是我们不用管那么细。
其实在我们的网络游戏中的,很多时候,我们的STRATTON只有一层,就是你跟服务器对就好了,那你跟服务器怎么去对时间呢,啊这里面的话呢就跟大家讲一下,NTP算法的一个最基础的东西。
它其实的基本原理非常的简单,就是说我从我的客户端在这个T0C的时间,就是C上面表示是client对吧,零就表示T0发出一个东西,就是这个T0C是什么,是我本地的时间,我发给谁呢,我发给服务器。
服务器收到我的时候呢,就收到了,就TES我收到了,服务器根据自己的中枢哦,我在TE收到了你的这个时间,S stands for server,就代表server,那么过了一会儿,服务器说我给你再回一个。
当然服务器经常会,它会在T这个二这个S的server的时间,把这个时间发给你,然后呢发给哪个包,然后呢你在什么呢,你在T3C的时候,就是在你本地的T3C的这个line的时间。
就是你的科莱的这个密码收到这个包,当然在你这个包里面的话呢,实际上你的作为这个客户端,我这四个时间我都拿得到对吧,我这个包里把这四个时间都都扩大进去了,那这个时候呢,其实就有一个非常简单的一个算法。
就是大家看到这个offset这个公式了对吧,这个公式的话其实就是一些简单的加减乘除,但这里面其实是有一个假设的,就是他会认为就是这个延迟的话,上行和下行基本是对称的对吧,然后呢你没有什么网络的波动。
然后呢其实我可以根据你的上行和下行,我会估算出什么呢,估算出你的这个RTT是多少对吧,那我可以估计,因为我又知道你在服务器,在那边耽误了多少时间,其实我可以反向的算出来说。
我跟你的这个就是说服务器之间的时差是多少,我这里举个更具体的一个例子啊,就大家比如说看到这里,比如说我在客户端,假设我在15。01分,17:01分哪个零零秒,我发个信息出去了,诶。
服务器收到的时候说他是说诶,他是无哪个17:01:32,我收到了这个时间,你看好像这个消息不应该要走30分30秒,对不对,这大概率就是我的客户端给你的服务器,这个好像不太对付对吧,我们时间是不对的。
好诶服务器说我在过了一秒钟之后,我在这个就是1分33秒给你传过来了,好客户端哪个时候过了一段时间我就收到了,但客户端这边显示什么呢,我这边显示的是什么呢,是这个这个时间是零五秒好了。
这里面就是其实有些概念就非常有意思了,比如说我怎么算这个路途上的这个延迟,Delay,其实很简单,就是我发出去的时候,零一秒五秒钟后收到,让服务器告诉我说呢,他收到我的包和他发回来这个包之间。
他花了一秒钟,所以呢我把服务器那边里面,消耗的时间给它剪掉,这样的话我可以算出来,说我在路上的弹幕就是五秒减去那个一秒,得到了四秒,好根据这个值我再看,如果有四秒的延迟,我理解。
但是为什么到最后我这边显示的是零五秒,您这边告诉我,你发送的时间是33秒,对吧,我不可能你就是你不可能在未来发给我的消息,这时候我就要算一个offset,这个公式呢就是用前面那个公式,你会发现。
就是说我的客户端那边的延迟和你相比的话,整整差我的钟跟你差了30秒,所以呢他基本能骨酸到一件事情,就是说如果按照这个延迟,比如说RTT是四秒的话,那我收到这个包的时间是什么呢。
应该是你服务器时间的33+4除以二,就是7。35分,而我这边的话显示的是啊,那个那个1分35秒,而我这边显示的是1分05秒,我就知道了,我跟你差了30秒,我得赶快往前拨,追上你。
所以你看到这个公式算出来你的offset是30秒,就算出来我的这个这个时间表,这里面其实这个公式非常好理解,很很容易解释,但是这里面其实有一个很危险的假设是什么呢,就是说诶。
第一我认为网络的环境是整个稳定的对吧,我不会一会快,一会慢,第二个呢我假设什么呢,这个我发过去的这个延迟的时间,和他发过来的时间实际上是对等的,这件事情成不成名的大概率其实它是不成立的,为什么呢。
因为大家想想看,就是在我们家里的网络,大家如果仔细看我们家的网络,哪个家庭网络里面有个特点,就是说你的下行带宽给的是很很高对吧,你下载片子时候非常快,对不对,你看的什么东西很快。
但是呢你的上行带宽呢一般都比较窄,但是呢延迟的话,那就是真的不一定,有的时候是下行带宽延迟比较大,上限的话反而比较快对吧,所以你的上下两路它其实不一定是对等的,所以说其实这个NTP的。
这个最基础的算法的话,他是要假设置两边是对等,它是用哪个RCT除以二,就估算了它的延迟,所以这也是这个算法呢它不太准确的地方,当然他肯定比你没有对的时候好很多,那真的对于我们的游戏引擎来讲的话。
我们怎么去对视呢,其实这里面的话呢实话实说,这个就是信息论会告诉你,就是说在一个不可靠的链接的前提下,我们是无论你做多少次校对,你都没有办法把始终对准哎,这个东西大家如果有兴趣的话。
可以用数学去证明一下,反正这件事情确实是你们要对准,但是呢我们可以尝试去猜,去逼近它,它怎么做呢,其实很简单,第一步我们把这个NTP算法跑一遍对吧,我们算出来说哎,我的客户端和服务器之间的差别。
但是服务器是是跌,所以我跟他的时间对准,那这个时候呢唉我们会做一件什么事情呢,我先赶快把我的客户端的时钟给调一下,这个时候呢我就快速的,比如说做三次做啊,做五次做十次,多少次都可以。
你只要愿意你跟他继续跑哪个NTP算法,你就算出一系列的offset,这里面就很有意思了,对吧对吧,就是你在前面第一步做完之后,如果假设这个网络符合我前面的假设,就是说它是一个稳定的上下行的呃。
这个这个延迟都是对的呢,那我的钟就已经对准了呀,但实际上没有那么理想,网络数波动了,对不对对吧,你鬼才知道什么时候有种波动,没关系,我多做几次,每一次我都算出一系列的offset这个值。
然后这个时候呢我去做一件什么事情,这件事情其实是非常hack了,就是说哎我把这里面所有的offset的值啊,包括这里面有RTT值,我也能算得出来,对不对,我把RT值最高于我平均值50%的这些。
这个这些教时准校准的话呢,我们把它给扔了,诶,有意思吧,比如说我做五次或者做十次,中间有两三次,他的RT d值比我们RT平均值要高个50%,我就不认为它不可置信了,我就把它扔掉,这其实是个统计学的思路。
对不对,那为什么RT t值高的值就被我扔掉了,其实很简单,就是因为这时候很显然网络在波动嘛,所以你这时候算出来offset就不可靠嘛,好他把这些可靠的这些RTD的情况下。
我算出来的offset这个值呢做一个平均,再用它最后对这个中进行一次调整,那这个时候我就跳就完成了一次对表,所以其实啊这个方法,他其实用了一些统计学的概念,大家其实它的原理也很好理解。
但是呢我们在做一个游戏,比如说我们任何一个客户端,开始跟服务器建立链接的时候,当握手成功的时候,一般你的第一件事情就是要把钟对起来,唉这件事情,所以说我们在讲这个游戏引擎课的时候。
这我也是想变变成哪个online games,online games的第一part去讲,就是因为我个人觉得这件事情真的很重要,我因为我以前我们在做游戏引擎的时候。
我们很多的bug可能是这个中配有对好导致的,就大家以后在处理一些比较对时间,敏感性的业务逻辑的时候,你会发现这件事情真的非常的重要,所以的话呢第一件事先把中队好,那么用这个NTB的算法。
再加上这个简单这个策略的话,其实你能得到一个基本可靠的这样一个重,但实际上我们自己实践下来会发现还是误差,就这个误差呢,嗯有的时候还可能还不是那么容易被去除掉,但是这这已经没有办法了。
其实我们已经没有办法去那个解决这个问题,因为真实的世界里面,这个网络链接比大家想象的要复杂得多得多,就是后面我们会简单提到,但实际上在这边的话呢,我们会只是让大家知道有个算法好。
那么有了这样的一个中队又整了之后,接下来就看我们怎么去彼此通讯了对吧,那么这里面就讲个很有意思的概念呢,就是说其实呢这个前面讲的就是说,虽然OSI模型很复杂,七层模型对不对。
我记得我在那个时候大学的时候学这个网,哪个计算机网络,这个这个这个架构的这门课的时候,那本书我记得是这么厚,然后我就觉得哎呀我的天呐,就做过网络怎么那么复杂呢,后来学着学着就发现我真的很复杂。
考试的时候觉得哎真的好难对吧,但其实呢你有了socket编程之后也就很简单了,对不对,我们就找到彼此的这个IP地址嘛,找到pot嘛,然后一通数据传不就完事了嘛,对不对,一通塞数据嘛。
但实际上当我们真的去写游,戏的这个业务逻辑的时候,我们就会发现这事儿真的不好使,就是为什么不好使呢,就是说其实啊我们再去表达一个,就是业游戏业务逻辑的时候,很多时候跟我们的人对话一样。
就是说A服务器我想做一件什么事情,服务器说好,那我去做好,做完之后告诉过一会,告诉我说我已经做完了对吧,那你想想看,如果我们要用哪个,就是socket写这个网络消息的时候,其实呢我们会定义很多的消息。
然后呢我经常代码写,写到一半说OK,我这个地方要send的一个消息出去了,好过下载完之后这个函数我要结束了,过段时间啊,等什么什么消息过来,我就一个回调一个函数。
这个消息呢还他不它不仅仅是这个消息本身啊,消息里面还有很多的参数对吧,他要payload your parameter,然后我要对the parameter进行解析,那这里面的话呢就很蛋疼了。
因为大家想想看,就是说当我们在写这个游戏逻辑的时候,你会发现就是说你要把这么多的,比如说我一会儿一个float,我一会儿一个vector4,就是我们一个空间的vector,一会儿是个颜色。
一会儿可能是个矩阵,一会儿可能是一个哪个怪物的血量值对吧,一会儿是这个怪物的一个一个一样的一个类型,各种各样很奇怪的数据,我要把它打包成一个网络的协议发给别人,而且要把这个协议定义好,你想想看。
作为一个程序员,你写到这一趴的时候,你就会觉得很难受,哎,反正我是很不喜欢写这个东西的,因为你会发现,如果就最早我们在最古老的时候,大家去理解游戏引擎那种,会想象。
游戏引擎会定义一个巨长无比的消息列表对吧,但实际上的话这个列表是非常难以维护的,那么另外一个还有一个问题是什么呢,就是说其实啊客户端和服务器之间,他们的操作系统都是不一样的,比如客户端。
很多时候我是在这个android的这个机器上,或者是IOS的电脑,是IOS的这个pad上面对吧,服务器一般是跑在LINUX上面,我们的这个这个语言都不一样,比如说我现在哪个。
就是我们的哪个操作系统都不一样,那么有的时候呢,比如说举个例子啊,比如说我做一个主机游戏可以联网,Export the place playstation,大家知道这两个平台最反人类的地方是什么。
就是我们前面已经提到过的,就是big ending,small ending的问题,就是说我的这个数据就是到底是高位在前,还是低位在前,对吧,我的packing都不一样。
那这个网络传输的数据是不是就不一样了,对不对,那这里面就很麻烦,那包括就是说我有很多的数据我要去对齐,我要去把它packing在一起,因为在网络的时候,有的时候我们都尽量希望四个by的一一层嘛。
那我一学primary传过去的时候,如果你只是顺序的压的话,哪个数据的话其实会很麻烦的,会形成像哪个狗啃的一样,就是数据一会长一会短,比如说我要把一个array传出去,那你这个消息怎么去定义呢。
因为array是变长了对吧,那就很麻烦,你甚至有可能你要传一个数据,他可能要把很多东西拆下来,那等等这些所有的问题,其实啊当我们去写一个游戏业务逻辑的时候,你发现这些都在你的面前。
而且你让一个写业务逻辑的程序员,去定义各种各样的消息,解决这些网络在传输的各种困难的事情的时候,你会觉得你让他做了一件,他其实特别不喜欢做的事,而且是特别容易做错的一件事情,因为你就想一个消息定义错了。
那边收到了整个解析就乱七八糟的之后,那整个这边不就全,这个整个底层逻辑全部会炸掉,就是说大家想想看,就是我们在客户端和服务器通讯的时候,其实有一种攻击,就是我们会给服务器发出来各种各样的。
就是乱码的数据,然后服务器呢它首先它要解谜,和它要解dio deck嘛,包括还有的时候是哪个,就是说description就是说解密,然后它可能会导致它会浪费大量的算力,解解码出来一个无效的信息。
但是他又很难判断这个信息无效,这里面其实有很多很有意思的东西,在要去解决了,简单来讲的话,就是说其实这个地方是特别特别容易犯错的,所以呢这个时候就是RPC就remote procedure call。
就横空而出,变态就是那么他的核心想法是什么呢,就是让程序员就像写自己的日常代码一样,我只是做一个函数的扩,然后呢我把我刚才传的参数传进去,剩下的事情,你是怎么把这个这个这个东西变成一个消息,去打包的。
去package怎么去THALIZATION,然后你在网络怎么样的路由,到哪个对方的服务器,然后对方服务器怎么去接到这个消息,怎么去,就依次去处理,其实处理一个消息都很复杂,不是收到消息马上处理。
他像是有个cash,有个pool对吧,然后再下一站pick up,然后呢再去怎么去处理它,怎么去distortion,这一系列所有复杂的东西跟我都没有关系,我一个RPC扣完之后,哎我该干嘛干嘛去了。
然后呢你这边做完了之后,你再把我一个call回来,然后我来处理就完事了,所以这其实是一个非常了不起的发明,这里面举个简单的例子,就是用go语言的例子对吧,你会发现RPC的阔气很简单。
就是你告诉我说诶我要扩server,比如说我的函数名是什么,我的parameter是什么,在server那边的话也有相应的函数诶,你只要这样一扩完之后,它通过一系列的这个消息的数据的准备传输。
我也不知道你下面走的是什么协议,没关系,你就走走走走走走走,走到那边哎,到最后哪个函数就被激活了,很神奇吧,非常简单,但是呢,这个会极大地释放我们的程序员的开发效率,同时的话它不会出错。
因为最怕的就是你的逻辑写错了,而且最怕的是你的数据进行packing的时候,数据一旦packing错之后,其实到那边就会非常的麻烦,所以的话呢就是说这是RPC一个非常重要的,就是说一个特性。
而且RPC我个人的感受就是说,因为程序员他不需要再去向定义,哪个是structing structure,那样的去定义那种复杂的网络暴体结构,然后呢。
他也不用担心这个ATIONDIRALIZATION的这个工作,因为在网络上很多是我们的数据都是加密的,对吧,还有很多加密和反加哪个解密解码的一个过程,实际上这些东西你全部都不用管。
而且整个后台怎么处理的,全部对你透明了,所以这就让很多程序员能够专注的去写游戏,游戏逻辑,所以RPC呢是现代引擎最标准的一个practice,对好,那么这样一个东西你看上去很好用。
那你怎么这里面就出现一个很有意思的东西了,叫什么呢,就是哎我们叫做interface definition language,就是那个就是叫界面定义语言idea,其实这个东西大家仔细想想。
我们这里面举举个例子,比如像哪个google的political buffer这个概念对吧,它实际上大家我们在什么地方讲过,这个同样的东西,就是在工具哪个地方对吧,我们讲过schema的定义。
这个地方它非常像schema的定义,就是说其实大家看我们的小引擎啊,你们定义的时候,其实很多时候这些比如说一个component的接口,是不是跟这个语言特别的现象,其实他们都是共通的东西。
就是说其实为什么反射这件事这么重要呢,也就是说它不不仅在我们的工具侧,在我们的数据的THALIZATIONDISORATION上很有用,其实对于component也很有用对吧,对于网络也是非常用的。
就是说其实我们所有网络的通讯,都通过这个idea的语言把它定义好之后,那接下来我们有一整套的这个东西去解决它的,就是函数指针的存储啊,解决了他这些数据的这个这个这个就是packing。
哪个serialize和DISCIATION,所有的问题它全部给你处理好,所以这里面的话就会引入一个很有意思的概念,叫做rpc steps,stars呢,你简单来讲就是票据存根。
就是说当我的一个客户端起来之后,当我哪个服务器起来之后,我们彼此会告诉对方我们的存在,然后呢我们就会注册一大堆的RPC,然后呢这样的话你的函数就知道了,说啊我有这么多的RPC可以调用对吧。
而且你每次扣RPC的时候呢,它可以在这个RPC的存根里面去查,就是说如果这个RPC没有的话,系统还可以给你报错,很多系统做的比较好的,比如像游戏引擎的话,一般我们不会允许这个系统crush掉。
我们只会给你报个错,说老哥你call了一个不存在的RPC对吧,你这个你这个哪个你回去查查一下去,但是呢我其他的业务逻辑该怎么走就能走,不会出问题,因为对于一个复杂的游戏来讲啊。
实际上它的RPC非常的复杂,比如说动辄就是几百个以上的这个,RPC的这种各种的扩,那么而且呢游戏引擎的版本,游戏的版本一直在更新,所以很容易出现一个,比如说没有来得及更新的旧的这个比如说脚本。
一段脚本哪一段代码对吧,他扩了一个错误的RPC,但是的话呢一般现代游戏引擎,它不会让你的游戏crush掉对吧,因为很多时候你说错了之后,只是某一个特定业务没有发声而已,但这件事情对于一个大的游戏来讲。
它不会是个大问题,所以的话呢就是当我们定义了一堆的这种,RPC的接口之后,通过id定义的时候诶,我们有一个stop compiler对它进行编译,大家不是前段时间对哪个。
就是那个我们的消引擎里面的schema的系统,很感兴趣嘛,其实schema系统,它本身也可以作为一个stop compiler对吧,但是呢如果你用的开源呢。
比如说political buffer这种东西的话,它的compiler是现成的,对不对,所以这件事情其实是一个非常啊怎么说呢,大家解决的非常好的一个系统,所以其实它的基础的设计思想是非常通的。
所以我就想你游戏引擎为什么特别有意思,就是你学到后面你会发现很多的设计思想,很多的方法它都是通的都在一起,所以这样的话就是说我们有了这个就是说id,我们就可以定义各种各样的RPC,而程序员的话。
这个时候再去写各种各样的网络应用的时候,就可以像写本地代码一样的对吧,就可以扩很多远程的这样的应用就很方便,那么其实的话一个真实的RPC啊,才游戏引擎里面的路径没有那么简单,其实就像刚才我提到的。
就是首先的话呢你的数据你跟RPC扩完之后,我要把你所有的参数给你进行THALIZATION,而且呢我还会对你进行压缩,很多时候我们需要压缩的,因为网络贷款很珍贵,所以我们要压缩一下,然后呢我们还加密。
因为在就是在游戏里面的话,如果游戏就是客户端和服务器端的通讯,不被加密的话,那黑客就很容易去攻击的对吧,他可以在里面注入很多他想要的逻辑,所以的话我们一定要加密,所以的话呢就是说这样的话。
到了服务器端的话,诶我们也是一样的过程,道路来一遍对吧,我想要解密,然后呢我要去解压缩,然后呢我还要再进行这个DISCIALIZATION,这样我那边的所有的相应的函数就被扩了,当然有些RPC呢。
它是通过我们讲的这种a reliable ud p出来的,比如说游戏业务相关,有的有的有的哪个就是那个就是RPC呢,他可能是通过什么呢,哎通过TCP连过来,就像我们前面讲过很多时候,比如说账号登录啊。
这些东西,我们去保证我们哪个握手,就是客户端和server端的握手成功,所以这个呢是一个真实的RBC在底层走的,这样的过程怎么样,讲了大概差不多一个小时20分钟了,同学们会会不会很着急,说哎。
为什么到现在还没有教我一点点怎么去做游戏,讲了半天,我只是学了一些网络协议,怎么架构对吧,知道一个RPC的东西,还知道了怎么去对对表,对时钟知道这么多,为什么游戏我还不会做,唉对你没有这些基础的话。
说实话作为一个游戏引擎的,这个就是online gaming,游戏引擎的话呢,你还真是做不了。
18.网络游戏的架构基础 (Part 2) | GAMES104-现代游戏引擎:从入门到实践 - P1:GAMES104_Lecture18-Part02-4 - GAMES-Webinar - BV1HN4y157Zq
那接下来的话呢,我们就讲讲真正跟游戏相关了对吧,大家最关心的就是,我怎么去做一个对战游戏呢,哎首先大家了解一下对战游戏呢,它其实有很多的这种架构,比如说最经典的就是这个p two p的架构,唉注意啊。
此处的p to p不是大家以为的那种p to p,对不对,我们的p two p是很正经的p to p啊,就是这个peer to peer,的这样的一个网络网络架构,那么p to p的架构呢。
其实现在游戏用的已经比较少了,但是其实早期的游戏,基本上都是用这样的一个架构,就是说所有的客人连到一个游戏里面之后,我们可以所有的人去通讯,大家彼此通讯,把我的状态broadcast给所有的人。
那个时代的话呢都是局域网游戏,大家如果啊差不多十几年前,20年前,如果那时候你还在什么机房或者网吧里,玩过游戏的时候,诶你们都知道这种p to p游戏的特点,那么现在用的最多的是什么呢。
比如说你有一个能通透ds对吧,你和另外一个小伙伴能ds,你们一起想打怪猎连联机对战的时候,唉你们其实用的就是p to p连接,你们就可以一起连到一个世界里面,b41 般来讲p to p现在用的多。
人比较少了,很多时候就是点对点,两个人直接联网,对战的时候,用一些啊进场的一些通讯的协议,我们就可以就是说去玩,那一般讲p to p的这种连接的话呢,我们基本上认为就是作弊啊什么的,我都不管。
反正你们自己玩的开心就好对吧,而且这个这个连接呢,相对来讲也会做的比较简单,比较鲁邦,所以早期的最早的这种对战游戏的话,用的p to p的还是蛮多的,那么后来呢就大家会发现,我还是有很多的业务逻辑。
是需要集中到一起的,比如说有些校验啊,有些胜负啊对吧,不然你每个人都是自己投票,对不对,说了算,那这个时候呢就会出现,我们会在这么多机器中选一个,说老哥你作为hoster对吧,好我们所有人连到你这来。
我们就可以进行这样的网络游戏,这也是一种特殊的比特币,这个东西的话呢,啊其实大家以前在机房里面,或者在网吧里面玩过一些早期的,比如像cs啊这种对战游戏的时候,比如说你打那个魔兽的时候对吧。
我讲的不是魔兽争,那个不是那个魔兽世界啊,是魔兽争霸这种游戏的时候对吧,星际争霸的时候,你就满局域网的去搜诶,有人开服务器吗,开了好,我连上你呀,大家一起连上你,那那那都是我小时候最快乐的时光。
就是说那个我们就这样的,去连接到一个游戏里面,这里面的话呢,其实已经隐隐的有这个专门的游戏,服务器的雏形了,但这种架构呢它的好处是什么呢,就是作为游戏研发商来讲的话,我不需要花钱去维护一个巨大的。
复杂的服务器对吧,你们自己作为玩家,就可以把你的电脑变成一个服务器,然后你们就可以玩,实际上的话到现在为止有一些游戏,比如说举个例子啊,比如说像沙盒类游戏,他们会允许一群玩家自己开一个小房间。
其实现在欧美还有很多游戏采用这种架构,就是由各个玩家自己在社区里面开发,自己的这个把自己的电脑贡献出来作为host,然后呢其他人找到他的服务器对吧,那有时候官方会nice一点。
就是提供一个叫全球服务器搜索,你可以搜索亚洲服务器啊,美洲服务器啊对吧,哪个离离你那个延迟最低的服务器啊,同学们如果经常玩一些steam的游戏的话,应该知道我在讲什么对吧。
比如说你们玩一个那个就是那个lost,ark的话,你就会知道你要哦不是losk,是那个就是说方舟,你就会需要去找到一个自己的服务器,在里面,去构建你自己的这个世界和城堡对吧。
其实呢这个就是基于这个玩家自己贡献的,host server的话也是一个非常popular的一种架构,它一般适用于什么呢,比如说一群人构建一个小世界,比如说几十个人对吧,不超过100人的。
我在这个世界里每个人去构建,比如说那个minecraft,好像也是这样的一个架构,所以呢这种架构也是这种top也是很常用的,那么其实呢就是说其实p图,p的游戏还是非常多了对吧,他就是说它的好处。
就是说对游戏开发者来讲的话压力很轻,但是呢很多时候那个host的那个server的话呢,有的时候他会它的性能啊,会影响它大家所有人的体验,但这个事情这个传统艺能就是,这不怪我对吧,我作为游戏研发商。
作为游戏引擎研发商跟我有什么关系呢,这一定是你家的电脑和你家的网络不好嘛,对不对,对不对,你的女朋友正在下片,所以你是说你跟小伙伴真的这一局,这个魔兽可能就没得打了对吧,这个事情只能你自己想慢慢解决了。
跟我们游戏引擎研发商是没有关系的,对所以说p to b的这种架构呢,我觉得是个甩锅利器吧,就是对这个引擎研发者来讲,是很爽的一件事情,但是呢对于更加的复杂的游戏,特别像现在的这个大型的mo rpg。
或者一些更加的这个非常专业的,这种电竞向的这种对战游戏来讲的话呢,现在一般都会用的是delicate server,就是专用的这个服务器,那么它实际上一般是有产品研发厂商,自己去提供这样服务器。
这种服务器架构呢,它的好处是什么呢,就是说它会在一个服务器端,维护一个一致的游戏世界,而且呢它能保证尽可能保证啊,就是说所有的用户能获得,相对公平且稳定的这个连接,所以的话呢嗯这个呢也是就是说啊。
这个架构的一个很大的好处,所以这两个架构呢,其实很多时候你很难讲谁好谁坏,但是的话呢,我觉得如果你作为一个小型的对战游戏,只是一个大家自己玩得开心的话,那我认为p to p或者说p to p里面。
你加个whole server,是我认为还是个好的结构,但是如果你真的想构建,一个非常大的一个世界,或者是一个非常高水平的一个竞技向游戏,或者你想赚钱的话,你要做的是delicate server。
就反正所有收费的游戏大部分都是这个,当然是这个时间收费,道具收费,这种游戏的话一般用的都是delicate server对吧,你都要在服务器上充值,你才能变强,对不对。
但是现在这个大家会骂你是pato v对吧,但是的话呢,你的基础架构用的应该是这样的,一个服务器,那其实呢这里面再多说一句,就是说实际上呢真实的一个网络,游戏的引擎架构的话,它实际上的话呢是比较复杂的。
因为大家如果看全球的这个互联网的,这个top结构其实非常的复杂,而且全世界呢有成千上万的这个,网络接入商,也就是说,我们全球有大概几10亿的网络人口,对不对,大家都要打游戏。
但是呢大家并不是直接连到互联网,它是通过一级级的这个网关的这个接入,那个网网网端的接入商接入进来,那么每一个人的网络信息都不太一样,其实当你作为更复杂的一个,一个网络结构的时候,你会遇到一个问题。
就是说其实这个用户之间,到你服务器的通讯会变得非常的慢,这个我举个例子,比如说我们把服务器假设放在啊,比如说韩国好,那么有可能这个就是,比如说亚洲的西亚的玩家连过了,他就会非常的慢,这种情况是很常见的。
那你怎么办呢,其实这里面有一个trick,就是说我们在各地各个区域,我们设置一个接口,一个一个像一个pto一样的,就是所有在当地的人呢,都连到你的这个po上来。
而这个po呢我会建一条cast speed internet,高速的专线,直接连到你的服务器,一般来讲的话他直接走一些光缆的专专线,这样它的延迟最小,而且也是最稳定,然后呢连到你的这个服务器来。
其实大家如果看,现在有些比较好的电竞游戏啊,比如说像league of legend英雄联盟的话,他们花了最大力气,就是在全球构建这样的一个骨干网络,这样的话形成一个更复杂的一个拓扑结构,拓扑结构。
所以大家想看就是top结构,其实不像大家想的那么简单,其实你作为一个真正的一个商业,经营情的时候呢,你就需要提供这样的一个服务,就是说允许别人设立各种各样的photo。
然后photo到你的这个服务器之间,建立高速的链接啊,网用户呢它是无感的,他连到的都是你的po对吧,他根据我比如在南美,我是在西亚,我还是在这个这个这个南亚,我有各自的接入口能连接进来。
这个的话呢是一个非常重要的一个,网络体验优化的一种方法,ok讲到这儿的话呢,基本上大家就对做游戏的这个那个online game,有一点那么一丢丢感觉了啊,接下来这一part呢我们要讲一下诶。
到底游戏是怎么同步的,这也是今天呢我们的课程中,跟online game好像是最相关的这一part,因为这也是online gaming的最核心的一个东西,那么其实游戏同步啊,我们首先去看游戏的分层。
大家还记得,我们在104课程一开始的时候讲过,游戏引擎分为很多很多层对吧,大家觉得哦一层层的,我现在已经学会了,我理解了什么叫工具存,什么叫core,什么叫这个这个这个feature层对吧,我们都知道。
但是其实这个架构它有一个假设,就是说这所有的游戏都是在single player,在我一个人玩的世界里面去完成的,这里面的话用户的输入也好对吧,它全是放在一个主体去运营。
当我们真的去做一个online game的时候,你会发现这个世界就不再那么简单了,就是说我们实际上每一个终端,大家都会有什么呢,都会有输入,都会有各种各样的game states,然后呢。
这个世界上面一系列的游戏复杂的逻辑呀,状态呀,他到底是应该放在客户端的,这个游戏引擎的这一层呢,还是应该放在服务器呢,哎这件事情好像就没有那么简单了,实际上大家去想一个最理想的游戏引擎的。
就是做一个对战游戏的通用方式,是不是说我在客户端只需要解决,说我的输入输出对吧啊,就是输入就是我的controller,比如手柄啊,键盘鼠标的输入输出是什么呢,就渲染渲染到我的屏幕上,其他的逻辑。
我希望最好全部交给服务器来做这件事情,对不对,这件事情还真的是对的,他去做我们这个这个叫地球模拟器的时候,我们这个叫宇宙universe模拟器的时候,我猜他老人家就是这么做的对吧。
他的他的物理模拟是一致的,我们每个人只是看了一个view而已,所以呢我们只是每个人负责输入我们的,我们的主观意志负责输入了,然后呢,我们的眼睛负责收集他老人家生成的光子,然后我们就形成了我们的view。
但是呢在游戏里面,这件事情其实没有那么的简单,那么其实呢在游戏世界里面,如果这里面是一个我们实时拍出来的,这种效果,就是说你看到了就是自己的操作,和别人看到你的操作,彼此之间是有一个延迟的。
其实你们是在两个完全不同的universe里面,但是我要感觉让你们感觉,你们是在一个世界里面,那么就是说这个游戏世界同步,的基础架构呢一般有三种,第一种呢我们先讲最简单的,也是最古老的。
就是那个step shot,就是我对这个游戏的状态不停地照顾,照的方法,那么这个的话其实现在用的人比较少的,但我会提一下,第二种呢就是大名鼎鼎的叫真同步,但是虽然现在有人在争论说。
这个东西到底叫不叫真同步,但我觉得这不重要,就是细节对吧,如果大家很纠结,我们叫lockstep,对不对,叫锁不同步,这个听上去好像有一点点高大上,不明觉厉对吧,但是我觉得真同步大家都能明白。
那么还有一个呢就是状态同步对吧,这也是现在用的最多的一种,也不叫最多吧,就是用的也是非常普遍的一种同步方法,这种这三种方法呢,基本上是现在游戏中最主流的几种,这个就是网络游戏状态同步的方技术架构。
先从最简单的这个step shot dation开始讲起,这个方法呢其实很古老啊,从最早的这个quick时代开始,它的基础思想是什么呢,其实很简单,就是说,客户端只负责把自己的收入发给服务器。
让服务器那边呢进行整个游戏世界的模拟,他把整个世界游戏世界模拟的一清二楚,五之后呢,他把这个这个整个游戏世界的状态诶,生成好,生成一个快照,就相当于把这一刻把每个人的血量,你的位置。
你现在应该是什么样的一个这个速度,什么样的一个一个朝向对吧,全部生成好之后,客户端拿到这些所有的信息之后,好,接下那个,你可以把每一个客户端的小人,想象成一个提线木,那个在那个虚幻引擎里面。
有个词儿叫poem对吧,我觉得这个pom这个词我觉得是蛮喜欢的,就是起子好,你就把那个你的客户端,各个小人放到服务器告诉你的位置,你就把它放到这样一个位置,诶,你这时候你无论用什么视角去渲染它。
那是你的事,你看到的东西它就是这样的一个东西,就这个结构啊,它非常的干净,非常的漂亮,就是说它保证了这个大家的状态的,绝对的一致性对吧,所有人只是把书同步给server server一片,模拟完之后。
整个世界的状态是高度一致的,你不用担心同步的问题,然后呢客户端它也很轻松,他只是在渲染,只是在在最后的一个绘制和表现而已,那么这样的方法的话呢,其实就是说啊,一般来讲我们在做服务器端。
那个状态模拟的时候呢,我们会希望他的这个就是说不要吃掉,我太多的这个计算的带宽,那怎么办呢,诶我会把它的帧率稍微下降一点,比如服务器端,我们很多时候说时针是不是就可以了对吧,但客户端的话。
我们可能希望更丝滑一点,我们希望是30帧,60帧,大家如果玩个quick的人,就知道那个简直是晕的晕头转向嘛对吧,这个打quick可以把你打吐为止对吧,那所以的话呢这个时候呢你就会发现诶。
好像如果我的服务器端的这个,因为你每次照照快照其实成本还是很高的,快照同步条的成本也是非常高嘛对吧,所以这个时候呢我们一般会怎么办呢,哎我们会在客户端那边的话,在两个snapshot时间做一些差值。
这样看上去更加丝滑一点,这个也是一个,就大家自然能想到的一个方法,就是然后呢,另外一个很有意思的事情是什么呢,就是说其实我每次照快照的话,实际上是不是会非常的,这个这个数据量会非常的大对吧,那怎么办呢。
诶我们可以,其实你会发现在一个游戏世界里面,假设我有100个a i t对吧,每个i t有这个,比如说20个到30个参数,其实很多参数啊它其实是不变的,比如说你在两针之间,1/10秒之间。
可能90%的小怪的血量,是没有发生变化的,对不对,甚至有30%啊,百分之五六十的小怪的,比如说它的位置啊,它的朝向有没有发生变化对吧,或者游戏你的激光有没有发生变化,那怎么办,这些变化就没有变化怎么办。
我就存一个地府嘛对吧,这个dif的话其实就是一个delta,那么用delta就能传过去,这里面的话我们举个例子,就比如说这个例子使用用的不是特别妥当,但现在确实很难再能找到这种快照。
基于快照的这种同步的方法了,这种游戏了,反正我已经找不到了对吧,所以我们就选了这个物理引擎的概念,就是说诶我假设要做个online的物理引擎的话,那么你会发现,就是说它这里面这个作者给出例子,就是说。
如果你使不使用这个delta的方法的话呢,你同步的可能是每秒钟4。5兆对吧,因为每一帧都要同步,它其实数据量很大,比如说我同步十次的话,我这个一个staff的数据量,比如说450k的话,我就要让它乘十。
但是呢如果我用delta的话,我传回去的话,你会发现诶你只要600多k就可以了,你可以数据量可以下降将近一个数量级,其实这都是一些很淳朴的一些方法,那么这样的一个方法的话呢,实际上就是说他有什么好处呢。
刚才我已经讲了,它的好处就是第一个它非常的简洁干净,因为这个大家如果写代码,你就知道这个server端的代码,写起来非常的清晰,然后呢so stay的一个快照下去,客户端全部通过就完事了。
但是的话呢他呢就是说客户端,有很多的算力就全部被浪费掉了,因为早期啊,就是大家知道最早的电脑的时候,很多时候我记得我在啊,很早以前看那个有些架构的,他会讲叫tm的架构,就是他认为服务器是算力中心。
然后每个客户端只是一个terminal,就是说你只是一个显示和你的鼠标,键盘input,但是真实的情况是,现在在客户端的算力是越来越强对吧,我们现在买一台,用ccr,买台pc,那不要算力太强爆棚。
对不对,服务器其实没有像大家想的那么充裕,尤其是你一拖11拖100的时候对吧,甚至有的服务器一拖一外,那么服务器其实算力根本就不够,所以的话呢这样的话有大量的客户端,算力全部被浪费掉了。
第二个的话呢就是说server那边的话呢,就是说它生成这个快照之后传递下来,这个数据量很大,因为你如果连接的人不多就好了,如果你连接的人多,你想想看,就以假设一个链接吃掉你500k的。
这个kb的这个snapshot这个带宽的话,假设有100个链接下来,你就是你知道吗,你的上行贷款要达到这个呃50兆左右,那就很吓人了,对不对,大家知道有上行带宽是很昂贵的嘛。
那其实很容易就会导致服务器那边的话,整个是用筛掉,所以最早的quick的话,我猜也应该也是局域网内部的游戏,他也很难在公网上去连,为什么,因为在公网上这么大的带宽传起来,大家会很很崩溃对吧。
所以说的话呢,这个其实是这个早期的这个,基于快照的方法进行同步的一个它的缺点,但这个方法呢,我个人觉得就是说他真的是非常的干净,非常的elegant对吧,我我一直认为就是说如果有无限的带宽。
我一定会这么干对吧,因为他从从最基础的原则上来讲的话,它的计算量是最低的,因为为什么呢,是就是说你十个人连起来也好,100个人连起来也好,我对这个世界的模拟,我只要去模拟一次,对不对。
而其他的价格后面会讲的就是,其实每个人都有点浪费的,第二件事情的话呢,就是它保证大家绝对的意志对吧,不可能这里面有作弊的空间,对不对,你只能改你的input的其他其他的状态,我决定了你,你怎么作弊呢。
对不对,所以所以说呢,而且的话呢就是说所以的话呢,它实际上是非常优美的表达,但是它的一个基础假设,就是我的带宽是无限的,才能做这件事情好,这就是最简单的一种最快照的同步的方法,那么第二种方法呢。
就是我们叫做真同步的这个方法,lock step,synchronization,首先lock step这个词的意思是什么呢,步调一致的往前走对吧,就是大家随着这个这个121的声音,同步的往前走。
感觉就是大家整齐划一,其实这就是locks about的原则,就是大家实实现某种那个某种程度上的,一种高度的一致性,那么其实这个呢,它的另外一个很有意思的解释是什么呢。
我觉得更像我们我们玩的这种回合游戏,打个比方,大家如果下棋的话,它是有一个round的概念,就是说你出一下你的动作,我必须要跟你确认之后,我才会有我的动作,我的动作你确认之后对吧,你才会有你下一步动作。
这样的话大家不会无序的出东西,这样的话我对整个这个游戏的状态,就这个game的,因为其实下棋打牌,打牌也是属于博弈嘛对吧,这个game game的话它是有序的,大家想象一下,如果我们研究一种这个发明。
一种打牌的方式,大家不需要依次出牌,大家凭感觉一通乱出,谁手快的人,谁牌砸得快,那你想看这个游戏基本上就很难设计,它就乱掉了,其实lock step的话呢,它的核心思想就是说大家别闹对吧。
我不管你每个人电脑是什么样,但是大家所有的信息都是以一致性的,同步的传给我,然后我一次一致性的去处理它,其实这就是lock step的最核心的一个思想,那他具体怎么去做呢,其实在游戏的这个引擎里面。
当我们去构建这个服务器架构的时候,它的核心想法就是说,无论你有多少客户端过来,你把你们的输入统一的交给我,然后呢我再统一的分发给你们,你们去做一致的sima,那你们得到的结果就应该一样对吧。
所以呢我的服务器很多时候就是做好,这个叫信息的汇总,同步转发的这种处理就可以了,这是最简单的locbd,那个真同步的一个思想,那这个的话呢最早的话呢就是啊。
用这个lock star这个思想的人就是doom,你看这都是大牛对吧,大牛总是大牛,对不对,就是quick用了这个step shot的方法,诶,杜姆人家又用了这个lock step,哪一个都是经典对吧。
而且到现在log step这个算方式算法的话呢,还是我们在现代竞技游戏对战,又是里面最经典的一个架构之一,对好那这个lock它去用它的时候,第一步是什么呢,哎你得itialization。
待会儿我们会讲的更深的原因,为什么这个步非常重要,就是这里面给大家举个例子,比如大家玩的这个王者荣耀对吧,大家linuleon应该也是这样的,就是呃我我我我我确认一下,反正王者荣耀我记得好像是真同步的。
那么首先呢,唉当你看到那个加载条在加载的时候,实际上他在initialize很多游戏内部的状态,这个时候,游戏里面几乎所有的这个核心的逻辑数据,必须是高度一致和对齐的,不能够有任何的不同对吧。
比如说就像你打王者荣耀,对不对,你对方出了什么英雄对吧,你出了什么英雄,那是必须是一模一样的啊,然后整个状态初始化的,是没不允许有任何的问题,为什么呢,这个东西就是这样的,就是我们各自在十几十台。
不同的终端上去模拟对吧,我们彼此只能同步的,我们彼此的输入,那你要是一开始的状态,有那么一丢丢的偏差的话,大家知道有个东西,什么叫butterfly effect对吧,就是蝴蝶效应。
那么对于这种复杂的游戏系统,你只要初始条件有那么一丢丢的,这个不同的话,那到后面最后最终的结果,可能就天壤之别了对吧,所以说呢就是lock step的话,它的初始化非常的重要。
我们要确保每一局开始的时候,大家的状态必须是高度一致的,诶光有这个够不够不够,后面还要讲的更复杂的东西好,那这个时候的话呢就很简单了,那说好,那我们怎么办呢,我的server很简单,我很公平。
每一帧你们所有的客户端把你的书交给我,我确认收到了所有人的客户端的输入之后,诶,我统一的把它发给你们所有的人,你们所有人拿到了这个客户端车,这个这是其他人的输入之后,你们同时开始模拟下一站。
应该发生了什么事情对吧,这个听上去极其的公平,就跟我们那个什么来着,就跟那个呃啊这个还很难类比,在生活中,这种东西有没有还是其实又满足的,比如说大家一起做个决策对吧,不要七嘴八舌的去说。
每个人把自己的决策全部写好,交给一个老师,老师全部收起来,然后呢,诶他把这个收起来的东西,直接写到黑板上一贴,你们看到了啊,几个人说左,几个人说右,你们自己看自己的角色是什么对吧。
其实也是这样的一个方法嗯,那么这个方法的话呢,其实就是说它有一个很好处,就是说非常简单而且极为的公平,但是它有一个非常明显的缺点是什么,就是说如果有个同学特别的拖拉对吧,大家就跟下棋一样的。
就是诶有一个骑手,他他出招总是很慢,或者有一个同学交作业总是很慢,结果你的课代表作业总是没有办法交上去,然后老师说本来要布第二第二天的作业了,或者下一个作业的时候,或者下一道题的时候,他死活不出来。
所以呢在这种这个lock step的最基础的实践中,你会出现一个问题是什么呢,就是说那个交作业最慢的同学,会拖慢所有同学的进程对吧,这样大家那个去玩那个就是啊,我记得好像玩所有对战游戏,今天我有。
就是我们所有人加载都已经加载完了,诶有一个同学他是小霸王,加载特别慢,我们就卡了,他这个还算了,我我能忍对吧,你是小霸王,但是我最不能忍的是什么呢,我打的很痛快的时候,马上要上,我要上塔了。
我要五杀的时候,诶突然这个一个老哥,突然就这个他的网络混合的东西,就出问题了,那我们所有人就等着他了,那这种现象的话呢,其实在那个比如在dota里面对吧,在那个星际里面,我们是经常常见的一件事情。
就是突然蹦出个对话框,告诉你说哎呀有人断线了,你要去等等等等等等,我也傻在那你也傻在那儿,但是呢他确实非常的公平对吧,所以所以的话呢,对于早期的局域网游戏的时候,我们很多时候就采取这样的一种啊。
真童工的策略,但实际上效果还是不错的,因为在那种局域网里面的话呢,这种链接都是可以保证的,那么但实际上当我们到了公网的时候,那么很多时候链接它就变得不稳定了,那怎么办呢,哎我们会对这个算法呢。
作为一个小小的优化,叫bucket synsynchronization,他的想法其实更淳朴了,就是说哎呀我为什么要一直傻等着你呢,对不对,我设定一个上限,我每隔100ms我要收一次信息。
我服务器没收到了,你本金就算做了操作怎么样,我不说对吧,我说我算你没做成,那我接下来我每隔一方面,我就是把现在已经交上所有的同学,他的结果发给大家就好了,那就意味着说如果你的你的操作没有输入。
没有被传上来,那是你的过失,我不管对吧,你要么就放到下一帧去处理,要么你就你就把它扔掉,其实这个东西呢相对来讲也是公平的,这个这个其实啊,这个在我们在做网络游戏策略的时候,我们有两个策略非常有意思。
一个策略叫做啊,我记得好像是叫网络差者获利,就是你网络差,你反而获利可以这个收益,但这个听上去不合理,对不对,还有一种策略是什么呢,叫网络好者,他有优势,其实当我们在做一些比较复杂的。
网络游戏策略的时候,这这两个原则,是非常要花很多时间去思考的,比如说如果你做的不对,你做成了网络差值获利的话,就会出现什么情况,就是小伙伴发现自己打架打不过了怎么办,拔网线拔网线对吧。
或者有人专门写了一些中间的那个那个,就是那个那个那个那个啊,一些一些黑客工具,就是说我故意的把我网络的这个p值啊,什么东西弄得特别不稳定,让服务器误以为我是网络拥塞了,其实实际上的话。
那个时候我只是给我自己争取,更多的瞄准时间啊,更多的这种移动的这个决策时间啊等等,这里面就讲起来就很深了,但是的话呢就是这个bucket liation,这个思路呢,我个人认为他就是说网络好者不吃亏。
网络差者你倒霉对吧,是这个策略,你好,你再快他也没办法,他100ms就在那个地方,你快了也没有用,但是呢如果你100ms你都赶不上的话,那是你自己的过失,所以说呢服务器是不管你的。
那么这样的一个策略的好处呢,它其实就是一个balance,就是说其实这里面确实它会产生一些,可能潜在的bug,或者是一些就是用户的输入变成无效的,这样的一些问题,但是的话呢。
实际上当我们在做这个网络架构的时候,我们永远是一个tradeoff,就是说我们不会在这种,就逻辑的高度的一致性,就是我严格的还原了用户的,所有的操作意图,和我的实时性之间做一个平衡。
那么如果你用最古典的这种,你其实是能保证它的高度的一致性的,但是呢就是这个如果你假设是用这个,就是啊bucket的方法的话呢,它其实更多的是为了这个实时性对吧,打的爽去妥协一些他的意志性。
但是如果我作为对战玩家的话,我肯定是选择这个这个,这个就是说这个实时性的,对不对,打游戏不就图个爽吗,我为什么要等你的小霸王呢,对不对,大家如果仔细看,现在很多对战游戏的服务器。
它的延迟优化到了20ms之内了,所以说其实体验是很舒服的,我才不要打那种小霸王的那个游戏呢,所以我我毫无疑问会选择这个这个,这个实时性的这个选择好,那其实这里面的话呢就是做真同步啊。
大家想起来原理都非常的简单,大家想想是不是几句话就讲完了,很简单对吧,但是这里面最难的一个问题是什么,你的整个游戏的核心逻辑,它都要具有deterministic,就是确定性。
而确定性这件事情其实是非常难的,哎大家什么在哪个地方,我们讲到了确定性了,我们在讲物理引擎的时候,讲到了确定性,对不对,那么当时就讲了那个物理引擎对吧,我一样的物理输入,我经过那么多复杂的迭代运算对吧。
跟几个雅克比矩阵,简称的结果还是一模一样的,大家想想看这玩意儿靠谱吗,我觉得这玩意其实挺难的,那么但是的话呢,如果这个东西会影响到游戏的逻辑的话,诶不好意思,或者叫我们我们更专业的说法,叫游戏的结算嘛。
就transaction,就真的它是有一次业务结算的时候,你还真的要保证它的确定性,而这里面传统的问题就来了,比如说浮点数它能不能保证一致性,对不对,你的rua number随机数能不能保证一致性对吧。
你的各种各样的数字数字与容器,比如vector呀,比如说那个list呀,各种tree啊,对不对,就是说说那个计算的action,这些算法它能保证一致性,对不对,你的数学库能不能保证一致性对吧。
更难的是什么,你的物理是mation,能不能保证一致性,对不对,还有就是说那个你的整个逻辑的执行顺序,就是因为大家知道就是我的component,打个比方,比如说我们的游戏引擎是component。
对不对,come on,我有几百个物体,每个物体的话有几十个con,那我有几千个这个组件,我要保证它的执行顺序是高度一致的,为什么他如果不一致的话,它的结构可能会产生不一样,哎呀完了,这个,这里面。
你这些所有东西都要保证一致的情况下,对吧,就保证这种deterministic确定性的情况下,你的真同步才是合理的,因为大家仔细想想,真同步这件事情是不是很微妙,就是说我们彼此是完全隔绝的宇宙。
我们只是设定了一样的初始条件,诶,我在用一样的这个输入变量,然后经过了比如说几千次,上万次的这种迭代,我们最终的结果都是一样的,这就是确定性的一个很难的一个地方,但这件事情在。
如果你要实现真同步的游戏引擎的话,你还真的需要实现这个东西,而这个确实确实非常的难,这个里面大家又回到了民间科学部分啊,就是大家想想看这个啊,我们的宇宙满不满足这个属性。
大家都至少以我们现在已知的物理学原理,我们认为这个这个事情是不能满足的,为什么哎呀,那么一点点的地方,因为什么呢,因为我们又叫不那个那个叫什么,不确定那个原则对吧,这个量子里面。
它很多东西它真的是真随机的,所以说它你就是一模一样的输入条件,它的输出就会有那么一点的差别,那想想想我们伟大的三体问题对吧,发生的时候,那这里的运动就是完全不确定的,那在宇宙星空中最多的恒星的组织模式。
什么是星团对吧,像太阳这种单核心的星系是极为少见,大部分都是双星啊或者三星或者星团,所以我们知道这个宇宙是一个混沌系统,高度不确定的诶,我们在但是在我们的游戏引擎里面,如果我们要实现真同步的话。
我们将要构建一个确定性的universe,哎这么一说就听上去很高大上,我们要构建一个确定性的宇宙好,那确定性怎么保证呢,那首先第一个更让大家很头疼的是,什么是浮点数对吧。
在计算机里面我们表现一个二的倍数,比如说整数是没有问题的,但是我只要保持表表示小数的时候,二的这个倒数倒数幂是可以的,14/2分之1/18都没问题,或者他们的组合也可以,但是我让你二除一个30。
666666,你就没有办法去表达了,对不对,这个时候那简单的解决方法是什么呢,你要符合i o p e的这个754的,这个负电数的标准,那么它从标准上严格上来讲,它是能保证你的浮点数运算的这个高度。
一致性的对吧,这个可能是我们最后的救命稻草,那么好,那这里面的话呢,其实你要意识到一件事情,就是说其实在我们刚才提到,就是在做网络游戏的时候,其实我们会面对各种各样的平台,比如说我们作为一个王者荣耀。
你手上拿的是个android对吧,那边拿的是一个ios,他两个的这个芯片的完全不一样,操作系统也不一样,但是呢我要保证,你们所有的运算结果是高度一致的,所有的数学库越好,你们的第三方库也好,就大家知道。
就是说比如说啊你那个第三方库来讲的话,其实在不同的平台上,它的实现都是有区别的对吧,那么所以说这个时候我们要保证,所有的数学库,所有的浮点数表达所有的这个啊数学运算,它都要符合我们的这个确定性原理。
这件事情就非常的挑战的,那么接下来还有什么呢,诶还有就是说我们的这个,就是说很多的数学运算,打个比方,大家经常在写逻辑的时候,比如说做动画的时候对吧,做一些这个反向动力学结算的时候。
我们要写这个三角函数,对不对,sin cos对吧,或者写一个e的多少次方对吧,log这些东西怎么办,你要用查表法,这个数值必须是精准的锁死的,否则的话,如果你真的交给他们,各自去算算出来的精度。
可能就非常的不一样,所以这个时候的话呢,其实这里面有很多的挑战,当然这里面还没有提到,就是哦随机数对吧,随机数我们必须要求啊对随机数,而我们前面有提到随机数啊,随机数内页在哪里哦,我会不会提到单独提到。
那么还有一点是什么呢,就是说其实啊在现在的游戏引擎里面,有一派同学在座的引擎叫做定点数引擎,其实如果大家是专注于做真同步的话,其实定位收引擎也是一个,现在大家特别热热门的一个研究方向。
就是说我们尝试用定点数fixed point,不要用floating point,然后呢用固定定场的整数和小数,它能做出整个的数学库,整个的这个物理的引擎,能够保证整个的游戏逻辑的。
他的deterministic,这一点的话呢,也是现在一个非常热的大家一个方向,但是很遗憾的是说,主流引擎大家很少用定点数这个去解决,但是的话呢,确实在很多特定的游戏场合里面,我们需要定点数这件事情。
大家听上去很可怕对吧,说哦天呐,我那么复杂的一个游戏,我要保证它的确定性,是不是非常挑战这件事情呢,啊好消息是说啊,严格来讲,你并不需要把整个游戏变成具有确定性的,因为这件事情几乎是不可能。
那你呢是把你最核心的业务和逻辑,把它变成就是deterministic的,就是说比如说角色的移动,角色的位置,角色的血量,角色的伤害结算对吧,这些全部都是deterministic。
但是呢比如像渲染这个东西,说实话你多一点少一点,问题也没有那么严重对吧,所以说呢一般我交给显卡,显卡那个时候我就已经没有要求,所以game state,我们要把它尽可能地做成确定性的东西。
那么另外一个的话就是随机数,这也是大家这个可能觉得唉,这个事情一没有想到,说连随机数这个东西我都要保证确定啊,确实真的是要举个例子吧,比如说你们玩所有游戏里面的话,我们打一个暴击对吧。
比如说我有30%的概率,打出一个三倍伤害的暴击,诶,不好意思,这个暴击1/3的概率真的触发了,比如说我在我这边,我一刻这个砍出去一刀,对方的那个状态的时候,我出我能够成功地砍出了个暴击。
你在你那边那个universe里面,我不会告诉你说我暴击了一个谁谁谁,你在那边,你用你的随处就是掷骰子,我一直我想说掷骰子,但有人告诉我,我们就叫织骰掷骰子吧,那一样的输入的情况下。
支出的投资就是一模一样的,那么诶我这边筛子啊啊,还是这个骰子舒服一点啊,骰子出来它是暴击了,你那边掷出的骰子,居然也毫无疑地翻到了一个巨大的六处,在上面,哇,我又暴击了,你想想这事就很有意思了。
所以说呢,随机数实际上也是要求严格的同步的,所以这个宇宙里面这个就是测不准,原理是完全不起作用的对吧,这个符符合水哪个哪个老人家的观点呢,符合这个牛顿老老爵爷的观点,老爵爷当年就在想说。
哎呀你看我宇宙三大定理对吧,整个宇宙,如果我知道现在宇宙中所有的原子的状态,我就可以倒推宇宙的过去,有可以顺延宇宙的未来对吧,所以那个时候整个物理学界最头疼的问题,是说谁给了这个世界的第一推动。
所以牛顿老爵爷整个后半生都在正在思考,这个精密的仪器怎么去运转的对吧,那么这个在我们的游戏的引擎的,这个世界里面,我们可以满足牛顿老爵爷的幻想,所以说如果我们把牛顿老爵爷,放到我们的元一周里面的话。
我们一定把它扔到一个真同步的,deterministic的这个游戏引擎的宇宙里面,他肯定爽的不得不要不要的,他发现这个世界太有确定性了,很开心对吧,所以呢render number这件事情。
其实是游戏引擎的精髓,就是其实游戏里面很多的运算,都要基于这个随机数,随机数是我们很重要的一个点,那么这这里面的话呢,它实际上是一个确定性的过程,所以呢在游戏引擎,客户端和服务器同步的时候。
他们首先要把随机数的种子给统一不好,而且呢随机算法也要高度一致,所以你会发现诶无论你是windows的还是linux的,你一次生成的一串随机数,它必须是一致的,诶这里面我再荡开一笔,就是那个啊。
大家知道就是我们讲量子力学的不确定性,里面有一个很著名的实验是什么呢,就是讲那个啊就是那个叫爱因斯坦嘛,他差了几十个事,他说你们是这个世界不是真随机的,这里面有个隐变量,只是我们不知道而已。
但是呢唉后来有个很著名的那个那个实验,双光子的实验,他证明了说这个这个这个东西,它这个概率分布是符合真随机,而不是伪随机的,诶这个我们爱因斯坦通知,当然他没有活着见到这个实验的结果。
所以呢这件事情的话呢,其实跟我们这个世界又不一样对吧,还是那个不确定性的,但是呢在游戏引擎的世界里面的话,我们真的有一个隐变量,这个隐变量是什么呢,就是随机数种子。
这个隐变量在我们的每一个人的一个neverse,构建的时候,我们同步好,所以呢在游戏里面的这些这些角色,这些pm他看到的世界他觉得是随机的,我们知道那是伪随机对吧,一切都在我的掌握之中。
怎么样想象一下很快乐,所以有的时候我前段时间看一部电影,忘了叫什么名字,应该很有名,就是那个头号玩家,后面的另外一部电影叫什么什么玩家来着,他就讲那个游戏世界里的m p c,突然觉悟了。
他有产生了自我意识对吧,然后开始跟那个你们的玩家,这个谈恋爱那个电影叫什么来着,我有点忘了叫什么,超能玩家是什么玩家来着,其实我在想,如果有我们构建的游戏世界里面,有一天我们的npc觉悟的时候。
他会突然他们会研究说,这个事件里,随机性是个真随机还是伪随机呢,也许他们做完了相应的实验会告诉我们说,诶你们骗我,这个世界里面的随机全是伪随机,它里面有隐变量,甚至他们可以反向的猜出这个随机数。
种子数值是多少,并且能够预测预测这个世界里发生,所有未来的事情,如果将来我们的游戏引擎,能够走到这一步的话,非常的兴奋吧,好ok,那所以的话呢就是说deterministic这件事情。
其实是我们认为真同步,是一个非常重要的一个基础构建,你可以认为它是一个基础,就是如果你不能保证游戏的state的,它这个这个就是说确定性的话,其实真同步的算法基本上是不能成立的。
这是一个很挑战的一个东西,那么其实呢,就是对于这么复杂的一个游戏体验,大家想象一下现代游戏引擎啊,那这个时候呢,其实你很容易一不小心就会写出一个bug,就是本来a这个输入就是一一个一局游戏。
大家想想看啊,双方都有几千上万个输入过来对吧,那么就是几千帧上万帧的模拟接触之后,诶,可能在比如说d500 多帧的时候,两边这个系统就有细微的差别,到这个就七八百帧的时候,你就很明显地发现。
两个人已经在不同的位置上了,而且有的时候,你看见这个人打出了一个大招,但是呢在那边他打中了一个,这个在一个科幻的那边,他是打中了对面的一个龙对吧,而另外一边他把你打了那个一个空气了,对不对。
这个事你就知道错了,但是作为一个游戏引擎,你或者说你基于你的引擎开发的游戏,你该给上面的开发者提供什么样的服务呢,其实对于真同步来讲的话,就是bug的tracking和debug其实非常的重要。
那这里面最重要的一个一个,一个一个原则是什么呢,其实你要去不停地去把你游戏的整个状态,把它存下来,比如说你整个memory的状态,你整个c的状态,这里要用到一些技术。
比如说你要用那个check on的技术,check on技术,比如说我把现在所有的变量在一起,我算一个md five,一个一个编码把它传出去对吧,然后我会把游戏里面所有的关键的函数的。
扩和the parmeter,把它变成一个哈希值存在,那那么这个地方的话我就不停的,就是当然不会是每一帧每一帧太废了,可能每隔五帧到十帧,大家都锁定好,我会把它内存中把它game存一下,这个快照。
我也存下快照,这件事情为什么这么重要,就是当我在一开开发期间,我一旦发现我的真同步失效了的时候,我至少可以根据这些memory的快照的check的比较,我我可以知道在哪一帧错了。
然后呢我再详细的去追下去,就会知道说哪一步的运算错了,所以这件事情的话呢,实际上对于开发真同步的游戏来讲,非常的重要,但这里面具体的怎么样的去生成,一个能够帮助你去debug这种确定性。
这个这个这个这个的,这个就是说login的系统的话,在这节课上我们就不展开,但实际上大家如果去写一个真同步的游戏,引擎的话呢,一定要注意这一点,否则的话啊大概率你会开发很久,但是呢你总是发现你跑不通。
因为你总会发现什么地方,有个地方你没考虑到光机意向,整个世界发生了蝴蝶效应,最后结果你完全不知道了对吧,那么其实这里面的话呢,其实在正同步的话呢,它虽然用了bucket这个方法。
但实际上我们还是会遇到很多的,网络的延迟啊,突然抖动这样的问题,那这个方法怎么解决呢,其实也比较简单,就是说真正的游戏中,我们很多时候啊把服务器传过来的真,我们会开始几帧,比如说一针两针三针对吧。
当我就是说a服务器那边出现了一些延迟,就是他没有及时的把那个针传下来的时候,我这边的逻辑帧,我本地的帧还是可以从八分,你取个数据,你可以认为它有个小小的蓄水池,这个思想其实是非常常见的,大家举个例子啊。
就是说啊,我们经常在网上看那个就是那个视频,比如说大家看到的艾伊藤对吧,你们看的电影是不是觉得都很流畅啊,觉得这个a这个帖子从高位看着很舒服,对不对,但实际上你们知道吗,如果你们去分析它的网络上。
网络肯定抖得都不像话了对吧,那为什么你们会看到那个电影,非常的稳定和流畅呢,实际上他们在各个节点cash了很多的数据,就是前后很多真的cash在那,这样的话,当你在本地发生的一些抖动的时候。
它实际上都会把你给smooth掉,所以用buff的机制去解决,网络的legging的问题,是一个非常经典的一个策略,所以说呢当我们在做真同步的时候,因为我们没有办法规避,这个就是说啊网络的legg的话。
那没办法,我们就诶做一些小小的buffer,把这些这个这些针我们把它catching在这儿,那么另外一个的话呢,就是说其实在做镇痛步的时候,一般服务器,我们并不会要求那么高的更新率,大家想想看。
现在游戏我们的刷新率到60,甚至到120了对吧,然后我我们一个网络的r7 t,就是将近100多毫秒,对不对,那我肯定跟不上你的速度嘛,网易网络波动一下,我突然一下子增加到100ms,也是很正常的。
对不对,那怎么办,哎我的服务器其实就是差不多十帧左右了,但是呢我会在中间插入很多渲染帧,这样的话,我如果发现你的相机在移动的时候,那我不会出现这种当当当当当当,这样一动对吧。
我其实这个相机的位置可以插值吗,这样的话,我在中间插入很多的渲染帧的时候,这个世界的状态其实没有变化,但是呢你会觉得这个整个游戏的感觉,看上去非常的smooth,但这里面有一些更加细腻的一些差别。
比如说我甚至对一些动作的可以差值对吧,这个人的动作,我可以把它从游戏状态剥离出来,那么我可以让他整整个这个状态,变得更加的平滑,也是一种方法,那这样的一个很大的好处,就是说,当我的这个网络。
出现了各种各样的问题的时候,我的逻辑真和渲染针,我的我的画面不会因此出现,这种各种各样的抖动,还有一点就是在前面讲渲染的时候,大家有没有记得我们讲一个概念,就是说哎we think。
就是现在我们的显示器对吧,它你的free buffer生成的东西,它的一帧帧的刷到那个就是显示器上,如果显示器刷新的频率,和你的这个巴菲尔更新的频率不同步的话,你就会出现一条线,对不对,诶,但是呢。
如果你把逻辑帧和你的渲染帧剥离开的话,渲染针可以相对稳定的工作的话,你就不会出现那种,就是那种中间有一条线的,这样的一个一个问题,所以呢这也是他我们把逻辑和渲染,在真同步这种算法里面。
分开了一个很大的好处,那么还有一点很有意思的一件事情,就是说诶,当我们这个真的不做个游戏的时候,大家想想做对战游戏,我们最容易出现的情况是什么,是我们会断线对吧,断线大家打个游戏对不对。
我正好在上上分或者上塔的时候对吧,突然我就断线了,那时候很着急,对不对,我得赶快去连啊,大家想想这个时候实际上无论是你的书,我肯定没输了,这我接受,但是别人没有停啊。
我的其他的小伙伴还在那一通操作猛虎啊,那这些这个世界已经发生变化了,那我怎么跟他去同步呢,诶这个你们就讲一个,很有意思的一个一个一个事,事实就是说,当我们在做这个真同步的时候啊。
我们的客户端不是那种只是大米的,就是很笨的,从那个server那边去接受各种输入,它其实每隔多少帧的时候,它有个kf,就是呢他会把当前这里面所有游戏的状态,我take一个快照。
而且呢我会把这个快照呢存在我本地的,比如说内存或者是我的磁盘上,这样的话保证我这个游戏机是崩溃了,我这个snapshot快照还在,这样的好处是什么呢,比如说今天从游戏开始,就现在从游戏开始打。
已经到了1万张了,对不对,我中间断线了,大概十几秒,我丢了的丢了,比如说几百帧,我现在9500帧等对吧,比如说我丢了十几秒,这是我回来的时候呢,我发现我上一个快照可能是九,就是9000。
比如说啊400帧,那我实际上等我回来的时候,诶,我发现整个大家已经走到了1万帧的时候,我其实只要追这100帧了,我不要去追那个1万帧的结果,那个1万帧的结果,你追着看下来追死你对吧,这个时候。
所以快照实际上就能避免,我们每一次从头开始追你整个游戏状态,因为大家知道这个里面的它的,就是整个游戏世界的这个这个变化,实际上是根据你输入的一个积分量,对不对。
每每一个frame make friend,这样积分上去的好,那这个时候呢就有一个很有趣的设备,叫什么呢,叫quick catch up,那么举个例子,比如说我们的游戏的正常逻辑。
诶当我发现我要追的时候,其实我可以干一件什么事情呢,刚才讲了一个很有意思的架构,就是说我把渲染真和逻辑针不分离到了吗,我渲染成可以跑得更快,对不对,诶这个时候你反过来了,说渲染你给我停了,不要渲染了。
没有意义,反正我已经落后了,对不对,我把渲染的所有的算力全部关掉,我就开始疯狂地跑,我的逻辑,这样我以十倍的速度,我总是能追上你现在正在游戏的进度,而且我前面又照了一个快照,所以我总是能追得上。
大家想想看,这里面这个策略就非常的重要了,这样我就能追上那个,这样我就不怕掉线了,掉线了,我可以再重连,其实啊实际上的话呢,在对于有些游戏来讲的话,我不仅会在客户端找一个快照,如果我在服务器端。
我也对整个游戏的state进行模拟的时候,实际上我也可以在服务器端,在某些key frame都在照快照,那这件事情为什么有用呢,照样说我客户端断线重连对不就好了吗,实际上这里面有个很有意思的东西。
是什么呢,就是说,当有的玩家太长时间没有醒来的时候,服务器可以给你一个更新的快照,这样的话能够帮你把这个游戏的状态给你,去set up,所以这一点的话呢其实很有用,那么它有更有用的一个应用场景是什么呢。
就是这个诶观战模式对吧,大家打那个对抗竞电竞游戏,都知道那个不能关照的电竞游戏,怎么叫电竞游戏呢,我一定要关照,其实关照这个事情就非常有意思,就是说它实际上跟断线重连,用的底层技术是一模一样的。
所以说如果服务器那边把现在当前,前面那个关键帧的信息发给你,然后呢,再把你miss掉的那些选手的input,一通传给你之后,你就可以追上来了,但是大家这里有个细节,就是说一般来讲观战防止大家用它来作弊。
都会故意的船慢,大概比如说呃几分钟的数据给你对吧,这样的话你就算爆点也没有用,因为那个就是这个,这个别人早就已经不在那个地方了,但是呢其实大家这里面就理解一下,游戏引擎的底层架构里面。
就会说它的观战模式,实际上适合这个断线重连用的是一套技术,尤其对于真同步呢来讲的话,它实际上就是用一个就是这个snapshot,就是对几个关键帧,我们照一些快照,这个快照是照在你本地也好。
招待服务器也好,其实都是一样的,那么然后呢再通过就是说一种cup的机制,能够迅速的追上去,大家如果看到有些游戏的这个观战模式,假设你是中途进去的时候,你反而可以看到之前的选手的这个,什么快进模式对吧。
看到整个游戏的过程,其实呢这个呢既是一种炫酷的feature,实际上也是他真实的因素,就是他真的是把前面的那个simulation,全跑了一遍对吧,给你看了一遍,那么如果有了这样的一个基础的话呢。
其实大家就又进到了一个,更有意思的一个东西了,就是这个啊回放对吧,所有的对抗对战游戏大家都想要回放,其实回放也是一个道理,就是我对游戏的过程中的一些关键帧,存下来之后,诶。
我就可以在各个节点之间来回拖动它,就是往后拖,其实就是时间有更多的input的进去往回拖,你没有,就是你只要没回到那个节点,其实呢我就是少少少去计算几个输入,那如果你越过了那个step shot的话。
我就退回到前面的那个kfc,去生成我的这个这个游戏的世界,所以其实有了这样一个基础的时候,大家就能理解,就是说基于真同步的基础结构,其实我们做观战,做动线,断线重连,做回放,他用的都是一套机制。
其实这就是一个非常有意思的一套体系,ok那么其实呢就是说啊,基于这种那个真同步的模式呢,它实际上还是会有一些问题的,比如说假设有人作弊怎么办对吧,因为最原始的架构中的话,服务器就是发给大家。
你们各自演算,那其实客户端可以作弊啊,他说我赢了,或者我杀死了谁谁谁,但是大家知道这里面其实很可能这个状态,他是不听你的,对不对,那么但是呢不排除有人,比如说在游戏里面进行一些作弊改。
修改一些必要不必要的一些状态,比如说我说我突然移动到一个,什么奇怪的地方去了,那么这里面的话呢,一个基础的机制是什么,投票机制,就是说诶我们每个人过一段时间。
都会把自己的游戏里的状态的那个check on,就是我的那个校验码发过来,如果有一个老哥跟他其他人都不一样,我就知道你的作弊了,那我就把你脚给踢掉,但是呢如果只有两个player怎么办。
哎这个叫服务器就比较麻烦了,其实服务器里面它会有一套游戏state,他把游戏的state的算出一个check之后,跟你去比较,如果发现不一样,我就把你踢掉,但是一般来讲,如果只有两个漂亮的情况的话呢。
呃有的时候大部分这种游戏啊,其实用p two p的价格就完事了,而且它也不是那么强的电竞属性,但是对于一些电竞属性很强的游戏的话,他确实要这样去做对吧,所以呢这是一个真同步。
经常遇到的一个就是反作弊的问题,但这个问题其实难度并不大,真正比较难的一个问题是这样的,就是说其实真同步啊,它实际上啊把所有的信息和状态,在你的客户端全部都有原则上来讲,比如说今天你去打一个。
就是比如说像呃这个这个moba游戏对吧,实际上的话呢你应该是有战争迷雾的,你只能看到你自己自己的这个区域,其他人我是看不见的,对不对,这样的话我们每个人不知道对方的声音。
我去那个就是说我去那个做任何操作的话,我要用我的判断预判,对不对,但是实际上你可以很容易地放入一个插件,然后呢把整个地图全开,你知道对方所有的状态,所有的数据对吧,因为这个每个人在各地都是全模拟的。
所以呢这个如果大家用最经典的,真同步的架构的话,其实就会有这样的一个问题,所以大家,这就是大家,为什么看到早期的很多真同步的网游的话,它很容易出现一种就是外挂,这个外挂会让你看到所有的东西一清二楚。
对吧,但是其实现在的这个真正的游戏里面,中同步用的不是那么单纯,他其实有很多方法策略会规避这件事情,但是的话呢如果大家实现一个最简单的,真通过游戏的时候,一定要去考虑,就是说别人外挂的可能性。
比如说我们假设作为一个呃,这个这个的动作游戏一样也好,那其实对方的小怪在哪里,敌人在哪里,别人在哪里,我其实都是一清二楚的,那么就是说lock step的话呢,这个方法的话。
实际上是一个非常好的一个一个方法,它就是对带宽的要求其实是最低的对吧,你只需要同步指令,那么第二个的话呢,就是说他的那个,就是说从开发的这个效率上来讲的话。
如果你解决了他的deterministic的开发,效率其实非常的高,然后呢就是说其实真通过游戏一个,我认为个人认为是最大的一个,好处是什么呢,这个引擎就是说它可以做一些,对打击操作非常敏感的游戏。
为什么,因为我们的世界是公平的对吧,后面会讲到那个状态同步的时候就会出现,你现在在哪儿,我现在哪,他两个是并不完全一致,比如说我现在就打你个爆头对吧,我现在就是一个cao,打出去特别帅,正好压着你去打。
那不好意思,如果不是真同步的话,其实很多时候这种判定啊,是有很多灰色的成分在里面的,所以的话呢,这是真同步的一个非常大的优点,所以大家可以发现就是对一些动作,打击感要求非常高的这种对抗游戏的时候。
那么另外一个的话呢,就是这种阵痛步的话呢,非常好做游戏录屏对吧,大家想想这个技术原理就明白了,我把所有的错输入指令全部录一遍,不就完事了嘛,对不对,所以非常简单,但是呢他的问题呢。
就是说诶保持这种意见一致性,其实是非常非常难的一个问题,而且刚才我讲了那个全图挂这个问题,其实对镇痛步来讲也是很头疼,因为他确实毫无保留的,整个游戏世界的状态,促使化是一模一样,大家的输入你的全部一样。
因为我是在每一个人university,模拟的是一个全宇宙,所以的话呢这个宇宙里发生的一切,你都应该知道的对吧,所以说,那么但是还有一点就是说正同步的话呢,就是当我们断线充电的时候。
如果不使用服务端的这个staff shot,这个机制的话,其实他的这个追赶,如果到游戏这个时间比较长,比如说打了一个小时的那种对战的话,哎呀那个追起来就比较蛋疼了,对不对。
你想要模拟多少个tik的操作呢对吧,所以说呢这是真东部的一个小小的缺点嘛,但是我我觉得瑕不掩瑜,真通部,其实还是一个非常了不起的一个架构,其实我们两种方法都用了,比如说我们在做cp模式的时候。
就是两个人联网打单机的时候,我们用的就是正同步对吧,但是我们在联网打这个大家pvp对战的时候,是6v 16的时候,那我们啊8月八的时候,我们就用了另外一种技术,这种技术是什么呢。
诶就是我们今天的最后一趴叫做状态同步,这个算法,那么首先状态同步呢,现在其实在网游中,用的已经应该是越来越多了吧,就是说很多对战游戏用的是状态同步,就是那个m r p g对吧。
就是那个大型多人在线游戏的话,这种就是生活类社区类这种游戏的话,基本上用的也都是状态同步很少,我听说有人用真同步做,那你们的战斗系统如果有的话,那只能说是我孤陋寡闻了,那么ok那么其实的话呢。
就是状态同步的话呢,实际上就是把用户的这种状,态信息给同步出去了,比如说你用户的输入对吧,我比如说我开枪了,我跳了,我怎么样,但这里面并不是,直接把玩家的按键给传出去了,他很多是把你的一些指令。
比如说我去跳一下,我去攻击了,我就向前移动了,这种状态去同步过去,那么的话呢,比如说发生了爆炸,发生了什么什么死亡,这些东西的话都会去进行必要的同步,而状态同步的话呢,它最核心的一个思想是什么呢。
就是说它实际上啊他不会把一个全宇宙,全世界彼此间同步,其实每一个玩家只是提交自己,部分的信息和部分的状态,每个玩家自己在模拟自己的世界,但是呢在这个server端,他会去模拟一个完整的全宇宙哎。
这就是状态同步,和其他前面两种算法一个很大的区别,就是server端那边它会进行,根据你们每个人的状态输入,它会模拟一个全的这个完整的世界,然后呢,他只会把部分的信息跟你相关的信息,发给你的客户端哎。
这就是非常有意思的一个点,就是状态同步它的很大的好处就是什么,就是说他防作弊的能力要好,那么一丢丢对吧,那么嗯所以的话呢你可以理解成,就是说每个每个人都说诶,我我在做一件什么事,我在跳了。
我再我再去干了些什么事对吧,我开了个枪对吧,我觉得我打中我打中什么人,一般叫做服务器判定了,对不对,哎服务器呢那边有所有的信息,但是呢比如说我在这个地图的东南角,服务器。
只会把跟我周边的这些相关的信息发给我,太远的信息,他不发给我了,这个时候我想做做弊器的时候,哎很多时候我做回不了,但是呢我周边的人,我想开一个透视挂还是可以的对吧,但是远处的话就比较麻烦了。
ok那么这里面的话呢大家去理解状态,同步的话,首先要学几个这个叫黑化,什么叫authorize,什么叫replicate,这几个概念的话呢,其实在且state synation转动同步里面非常常见。
首先大家理解server,我今天讲中间的那个server服务器,服务器是跌对吧,服务器是authorized server,就是任何事情,服务器说你不对,那你就得承认就不对了,这是一个做状态同步的。
这个文案架构的一个基础假设,那么对于这个客户端来讲的话呢,其实很多事件很多state的有一个客户端,它是有发言权的,比如说我自己操纵我自己向前移动开枪了,那肯定是我说了算,对不对,所以我是auths端。
那我呢就是说是我一个player自己的一个client,我说我但是别人看到我的时候,在那你没看到的,我其实是一个什么呢,是我的一个replicate,是我的一个复制品而已对吧,哎这个有意思了吧。
这样就是在你的university看到的,我其实是我的复制品,而这个时候的话呢,很多时候它是依赖于服务器端告诉我说,诶往西在地图的什么什么坐标,它面向哪儿啊,你在那边把我的一个replicate放在那。
所以其实这个authorized replicate also server,是当我们去写这个state ciralization,最核心要理解的这个核心的概念,这也是可以假设说我们认为就是这个啊。
states connection的话呢,最容易出问题的地方在这里面举个案例,我这边本来是个哦视频可以播放,那其实呢从player一角度来看,他是author的短袖,诶,我开火了。
它实际上是replicated的,它实际上是他是看见了玩家一开火,是player一把自己的一个动作fire发给了服务器,服务器呢说player 1 fire了。
并且把这个player 1 file的这个状态,注意啊,是发给了所有的client呢,除了player以自己之外,但是有的时候他也会发表的自己,那就是confirm,它有的时候会确认,这没关系。
这都是细节,但是呢他会发给尽可能发给所有的client,而player作为这个class之一,他收到了,他说好,那行,我把这个在我那边,你的replicate作播放一个开火的动作。
然后你就开始去战斗了对吧,而这个时候呢,诶这个普雷一打出的这个导弹,他就开始去模拟了,对不对,在服务器端,客户端都在模拟,就是这个时候,大家没有必要同步那么多的细节。
反正但基础的发射参数定向定在那儿的话,一个基础的物理弹道呢,不会有太大的区别啊,反正你看到的轨道基本上都是一样的,这个时候server,假设那边说,你小子好像正好打中了远处的一枚军舰,哎这注意啊。
这个时候不是你自己说,普player一说我打中了一个军舰,你觉得你打中了不算数的,是服务器说我觉得你打中了一个军舰好,这个时候他就会给所有人发个广告,说诶你把这个炸弹给我销毁掉了。
播放一个巨大的爆炸特效,然后呢呃这个就是说你有个hit event对吧,然后那个军舰被打得很惨,炸掉了好所有的客户端,收到这个消息之后,他们就播放一个那个军舰那边爆炸,冒烟的这样的一个效果。
其实这里面就是这个,非常简单的一个example,但这个example的话就完美的解释了,就是station,它的核心思想,就是说每一个人提出他自己的动作动作,但是整个世界的核心业务逻辑。
是由server来完成的,而其他的很多其他的观众就是,你是表演者对吧,你有一堆的围观者对吧,其实围观者他自己也是个表演者,那我们只是把自己的动作提交个server server,最后判定你的动作是有效。
无效和动作什么结果,然后呢server那边也会产生很多新的一些结果,他会反向的把这些结果,同步给各所有的客户端,当然了,你的动作也会被同步过去,所以听上去有点复杂,所以说这其实就是那个状态同步的。
这个思想的核心,那么这个思想它有一个很大的好处,就在于就是说它并不要求所有的客户端,要保证就是deterministic,因为你就像物理模拟不太一样,没关系对吧,最后的结果只要一样就好了嘛对吧。
你打没打中巡洋舰,巡洋舰,比如从天上掉下来,然后呢,这个这个这个你在半空中被你炮弹打中,这个听上去很玄乎对吧,但是的话呢在服务器端他认为你打中了,ok你就算打中了,你在每个客户端,它那个巡洋舰的位置。
都有那么一丢丢的区别,甚至你觉得那个导弹已经miss掉了,但没关系,不妨碍,只要你收到服务器的一个消息,说你被命中了,你就被命中了,你不要跟他争论。
因为他是那个authorize the server对吧,他是爹,你们都要听他的,所以他又避免了这你们的歧异性,那么这里面就有一个很有,所以这个这个c程式的核心算法就是这样。
非常核心思想就是这样非常的简单对吧,它不像真同步那么的苛刻,它又不像step那个shot synation那么多,那么的粗暴对吧,把整个状态同步,它只同步每一帧,是同步些关键性的变量的信息。
它天然的就带了德尔塔特性,就是状态没有变的东西,它不同步的,对不对,你这一个一个n p c站在那没没任何反应,那就不同步呗,还有一点什么呢,它天然自带的裁剪属性,就是说跟你这个客户端没有什么关系的东。
西,它也不痛苦,其实在下一节课,我们会讲一点点简单的这个a o i的算法,就是area of interest,就是说对于每个客户端,我们服务器会算说诶哪些信息你是关心的,哪些信息你是不关心的。
就不同步了,所以这里面再讲一下民科的东西,如果是状态同步的话,我觉得也是有可能的,所以我们每个人看到的世界,只是这个universe的子集对吧,像我们人类只能看到什么呢,致敬那个900多亿光年的。
这样的一个一个一个一个球体对吧,900亿光年之外的世界跟我们没有关系,所有的信息给我们就可以了,其实所以这么讲的话,又是个状态同步的一个架构对吧好,所以的话呢就是说这是针筒啊。
状态同步的最简单的一个思想好,那么这里面就会产生一个,很有意思的问题了,就是说你想看看我是author端对吧,我决定我自己怎么走,但是呢真实的情况是我决定我往前跑,我这个往前跑的这个鼠标。
往前按的这个动作对吧,或者是往前走这个动作,他要先同步给服务器,服务器confirm了我的这个这个动作,然后呢把我的位置往前移了那么一丢丢,然后呢诶再等他再回来,我一看到说哦我往前移了,比如说0。
5米哈,我这个角色往前移了0。5米,但是这个时候你会发现啊,就是因为有个有一个网络延迟的情况下,比如说100ms,200ms,我会觉得这个角色很傻对吧,这个问题是什么。
这叫dumb client problem,就是这个愚蠢的客户端的问题对吧,就是你会觉得这个角色特别的笨,你按下键盘鼠标没反应,过一会儿它突然就动了,你想想这个感受是挺难受的,所以呢这个问题呢。
实际上需要当我们做状态同步的时候,这个问题是非常严肃的一个问题,这个问题呢你要做两件事情,第一个是什么呢,你在客户端,既然你自己说了算,对不对,那你要做个预测好不好对吧,我假设我这个操作是合理的。
那我就知道我下一步应该移到哪去,第二件事情是什么呢,你觉得你合理不算数啊,服务器会觉得你可能是错了呀,那怎么办呢,服务器一旦发现跟你不一致的时候,你们两个在和解。
所以呢有个叫server reconciation conciliation nation,就是说我们两边要去和解这件事情好,那client prediction呢,它的基本思想呢其实是非常的简单。
就是说当我在authord client端,我放了一个向前的移动的时候,我本地呢就往前移动半步,这时候等我server来了,消消息的时候,确认往前移动的时候,我再去跟server那边对齐。
如果我已经完全移到了,那我就不去动它好,那么其实这里面的话呢,就是很著名的一个守望先锋的例子了,就是说你会发现那个绿色的条,就是我的authors client对吧,你会发现我在我的author里面。
我的世界总是跑在前面的,为什么呢,因为我告诉我的世界发生了什么事儿的时,候,到服务器那边的话,我要发过去,他那边就已经比我慢了,等他再回来的时候其实是更慢,所以呢在这个守望先锋里面的话呢。
他先做了个策略,就是说他对这个rtt是有个古迹的,假设r t t是这个160ms对吧,大家想这个其实很可观啊,将近接近于1/6秒左右了吧,他说我以前我我去往前预测什么的,一个half rtt。
就是半个rtt的时间,再加上呢一个kt frame,就是一个come on frame,一般是60帧每秒,因为那个守望先锋在追求爽感,照新率特别高,就是60帧,那么好,16ms,那我就永远往前预测。
大概是96ms的动作,然后呢我等服务器端那边的东西回来之后,我再去跟他去对齐,然后这个对齐过程其实是个差值的过程,它不是一瞬间把人移到那个点,肯定是在下一帧里面我去往前移动啊,尽可能让我们的移动去平滑。
我在下一站下一节课,你们会给大家仔细的去讲,就怎么样的去进行这样的一个,就是这个啊这个平滑的差值算法,其实这里面有很多细节的东西,但这里面不重要,就是细节,所以说其实啊,就是大家看到游戏里面。
那种丝滑的操作的爽感,你是要用本地的这样的一个预测,才能够达到这样的一个结果,当然这是or watch的自己的一个策略了,其实不同的游戏不同策略不同对吧,我个人看到这边有,我一想这个策略挺好。
我想我们自己做引擎的时候,是不是也用一下这样的一个策略,那么其实呢当我这个时候自己做完之后呢,实际上siri那边的话它是要进行一个和解的,那怎么去做呢,其实啊我们在看一段的话。
我其实server我一个消息一个动作发出去,从server回来的话,这个周期其实蛮长的,可能100多毫秒,我本地的话可能已经跑了好几针了,那我怎么办,我这个时候呢,就会把我本地的每一次预测和每一个状态。
全部把它八分到一个,这个就是一个一个一个序列站里面去,这样的话呢,当server的每一个信息回来的时候,我就会跟他那个过去的信息去去检验,这里面有个细节是什么呢,就是说往回退啊。
就是当server告诉你说你现在在位置,这个比如说x点的时候,实际上是server在比如说零点啊,50ms之前的认为,假如你们rt d是100ms,为什么呢,因为server算出来说你现在在x点对吧。
其实你你在你这时候已经跑到x一撇,点x一撇,假设不等于x是不是说明你的预测错了呢,其实不一定的,为什么,因为server回来的消息他还要走半个rtt,对不对,所以你要回溯到前面那个饭卡t t。
看一下我的位置是不是跟server讲的一样,如果我跟server讲的一样,那我明白了,我跟server的世界其实是同步的,只是因为他把这个信息传递给我的时候,产生了延迟,所以说这个时候呢。
你就要你就是不是只能不是,只存你当前的状态,你还要把你在之前一丢丢的时间的状态,全部算好,这个地方听上去有点抽象了,但是呢大家去理解一下,我是一直讲到说信息的传递是要有时间的,对不对。
然后呢我们的时钟永远无法对齐的,我收到一个信息,就像我收到一封信一样的话,我其实不知道你是什么时候寄给我的,对吧我当,但是我可以根据邮邮政的这个,就比如说从北京到上海,寄封信的这个平均时间。
我会知道说哦,我是7月8号收到了邮邮件,那我预估你这个邮件是7月5号发的,那你告诉我说7月5号我此时应该在河北,我看看我的状态,在河北,如果我的状态河北说明我是对的,我就不用动了,但如果我发现诶。
我那时候其实已经到了那个就是天津啊,北京的近郊了,那我就知道这里面有东西可能搞错了对吧,这其实就是so server,可和解的一个一个一个一个重要的点,那么这个时候的话呢。
就是说如果我们发现我们我们在那个server,那个时间点跟他的状态不一致的时候,那不好意思,我们就会必须要按照server的要求,反向的去校正我的行为,因为sa那边我们永远认为是他对的。
这件事情为什么特别的重要的,举个例子,就比如说你在你你对面有个玩家在你面前,比如说施了一个魔法,生成了一堵墙对吧,他可能觉得在那个0。1秒前试了富强,我们两个,因为我也不知道那个玩家的时间。
因为玩家给我传来的数据时间会更长,那这个时候我认为我已经一步跳过去了,但是呢server那边判定我跳不过去,这个时候如果你们俩的状态,一般来讲,大家在正常移动的时候,不会有什么太大的问题。
但是呢一旦就是这个游戏世界,因为其他用户的输入,或者是游戏机制发生了一些变化,产生了一些变化的时候,我们可能会跟server产生冲突,而这个时候的话呢,这个处理机制比较复杂,但是它最核心的一点就是说。
我们必须要跟server进行一个和解,那和解的方法只有一个,其实就是客户端跪地求饶,说server,你对的,我错了,我一定改对吧,这里面出现一个就是比较有意思的案例,就比如说你面前突然出现了一座墙。
比如说一个魔法与魔法墙之后,客户端不知道自己觉得我已经出去了,然后你会发现你身后就在你本地看,你觉得你身后有勉强,你觉得自己特别的厉害,但是呢the server端判定是说在你启动的一瞬间。
对方已经把这个魔法相册,你们先挡起来了,不好意思,你被挡回去了,所以说大家看那种状态同步的游戏啊,经常会发现这样一件事情,就是你觉得好像我穿过了一个什么障碍,我的门在关上的一瞬间,我已经穿过去了。
但是你过一会儿又被拉回来了,大家想想看,我们以前玩一些游戏,游戏有没有被拉回来的感觉,其实基本上就是你跟server进行,reconciliation的时候,得到了这样的一个结果。
所以呢其实这个东西的话呢,实际上在那个server那边的话呢,其实我们是需要一个ring buffer去存储,这个就是我们在过去几成存在这样的东西,然后当我们出现了这样的一个问题的时候。
我们这些reber之后的无效数据全部会无效,全部重新算一遍,这个听上去很尴尬对吧,但是没办法,server是跌,你就去听他的,这里面举个有意思的案例吧,给大家举个有意思的案例。
就是这里面这是守望的一个案例对吧,玩家本来做了一个快速喷气,往前冲的这样一个动作,诶,当然对方一个玩家放了一个空墙,你就被挡住了对吧,你就过不去了,那这个其实就是一个啊很典型的一个。
就是这个server conciliation的这样的一个结果,那么这个在online游戏里面其实是非常常见的,就这里面的话呢,其实又回到我刚才提的那个问题,就是这里面到底对谁不利对吧,到底是对对。
那个就是叫啊速度慢的玩家不利啊,那个网网速不好的玩家不利呢,还是对网速好的玩家不利,这里面呢是一个很典型的,就是对网速不好的玩家不利,因为你对这个世界,获得的更新是比别人慢的,如果别人的网速好的话。
能够及时的收到server的各种状态,他又及时的把一些新的状态,input输给sofserver的话,那实际上它能快你一步作出反应,所以这个时候就是说给家里换个好网卡,有的时候可能是你的选项之一对吧。
这也是我们在游戏引擎架构上的话,这个有意要做的这样的一个策略,那么其实的话呢就是更复杂的问题,因为其实你客户端发出去的很多操作,特别是你以前往前按就往前跑,大家想一下我玩cs的时候对吧。
我去拿个小匕首还是冲锋的时候,我是不是一路按着w往前冲啊,对不对,但是呢其实这样高频的往前移动的,这样的一个信号,他有的时候在网络环境下会丢掉,那这个丢掉怎么办,其实呢server有一个非常简单的策略。
就是说它首先会把用户的这个输入,有一个buffer rain buffer把它存起来,就是他不会只存你一帧的数,它会存好几年的数,所以他也做了一个小小的buffer,保证server的逻辑它是流畅的。
第二个呢,如果他在一定时间里面,他已经收不到你的任何输入的时候呢,他有的时候会自动的,把你过去的最后一次操作可以duplicate,所以说比如说你断网的时候,我们大家经常打网游里面发现一个情况。
就是你其实这边已经断网了对吧,你已经双手离开键盘了,但是你在你看你朋友那边,你自己的话是在那边一直跑跑跑跑跑,直到跑到血压处摔死或者被人爆头了,其实呢这就是一个server里面处理,但这个东西呢其实啊。
它是每一个游戏都会有自己的选项吧,但是的话呢我觉得啊,这也是一个大家很常用的一个practice,就是还是回到那个,你,当我们一旦从单机游戏变成网络游戏的时,候,你发现你面对的是一个。
极其不稳定的一个世界,你需要做各种各样的策略,确保大家感觉大致一致,的这样的一个游戏体验,那基本上的话呢就是讲到这儿,我们的状态同步的核心要点讲完了,因为这是104课嘛,所以我们没有讲的特别的深对吧。
那么其实的话呢就是状态同步和lock step,同步的话,现在是两大主流的这样的一个一个体系,那作为我自己个人来讲的话,我刚才我也讲过,就是我一直认为,真同步呢是一个非常好的东西,它特别适合那种对抗。
抗打击感特别强的游戏对吧,然后呢,竞技游戏,我也觉得就是用真同步是个蛮好的选项,但是他对网络的要求是蛮高的,那么另外一个他对你引擎的要求也很高,因为要求你引擎核心逻辑,业务确定性是非常高。
而且他也非常的鲁棒,那么状态同步它比较适合处理那种什么的,就是网络本身比较复杂,不太稳定,而且游戏业务也比较复杂,另外一个的话呢,就是说我的整个游戏参与者特别特别多,游戏业务也比较丰富的情况下。
其实状态同步是一个比较主流的一个选项,就比如说我们构建一个几百人,上上万人在一起的这样一个游戏世界,我不可能把这上万人在一起进行的,这种战斗全部在一起,就是每在在每个客户端都模拟一遍。
这个其实你根本跑不动对吧,那这个时候你可能真痛,不是状态同步是你唯一的选项,但是两个方法的话呢,完全趋于大家的一个一个自己的决策,实际上的话呢就是啊,我看到现在的很多引擎啊,打个比方。
比如说呃现在商业引擎,就是说呃很多以及缺损的,它都是能实现状态同步对吧,rap cde啊,这个我信号我这边r p c调用都很简单,但是呢,你如果要把这个引擎改造成真同步的话。
一般来说都要求团队很小心地写很多自己,hq的代码,然后呢把这个阵痛过去实现好,好像现在真正的就是专门为真同步游戏,做的这种有性情啊,我好像没有见到,但是有可能有可能就是说我接触的不够多。
但是很多时候真痛苦的游戏,都是要自己去改引擎,能实现这样的一个效果,但这两个都非常的有用,好讲到这一part的话,基本上就讲完了对吧,那我的问题就是学了这么多东西,我们今天讲了两个半小时对吧。
那我们是不是能够做一个online游戏的呢,那实际上呢我的答案是非常悲观的,学了这么多,其实大家还是不会做一款对战游戏,为什么呢,因为关于位移怎么去同步对吧,大家的这个这个射击判定怎么去保证。
我们的判定都是一致的对吧,更细微的,比如说这个这个这个一个大型,真正的网络游戏该怎么去架构对吧,我的信息怎么去分布,这些问题如果不解决的话呢,其实一个对战游戏还是做不出来的。
所以呢这些东西我们放在下一节课,给大家去讲,今天的话把这个online游戏的基础的foundation,告诉大家了,对我们从最基础的协议开始讲起,这也是啊就是大引擎的快乐,你会发现做引擎。
连基础的协议都要自己去架构好,ok那今天就是我课程的主题,最后呢是我们这节课的,这个就是同学们的课程组的小伙伴们,其实团队还是非常努力,非常那个用功的做了,准收集了很多很多的资料,那么另外一个的话呢。
就是这是我们的各种各样的参考资料,比如说网络协议的啊,这个就是网络基础的网络同步是怎么做的,对吧,还有就是这个各种同步的东西哇,这真面文章蛮多的好,ok最后到了我们的q a环节,同学们也没什么问题啊。
ok这个第一个问题,同学问我说,单纯的真同步不能做战争迷雾吗,呃首先第一个肯定是可以做呀,正同步肯定可以做战争迷雾,因为就是说啊,你在那个就是根据每个玩家的位置,甚至画一个战争迷雾都是没有问题的。
但是呢我刚才讲的就是说原则上来讲的话,如果你的游戏客户端被别人破解了,比如游戏里的state的被人读到了之后,那么他很容易写个外挂,把你游戏战争迷雾盖住的,那些东西的状态和信息全部可以拿到。
其实这个地方我自己也在思考,就是我相信很多游戏已经做了一些处理,但具体什么方法的话呢,啊我也回去研究一下,有可能有解法,但目前就我的知学识的话,好像我还没想到这么一个好的办法。
就是说在真同步的引擎里面怎么样避免,就是怎么去藏住,那些我不想让别人发现的信息,这里面其实有一些方法,就是说其实在有些游戏的,就是那个就是防作弊,它有一个叫加壳,它可以对一段一段指指定的内存进行那个。
比如说内存扰乱扰乱啊,乱序啊,加密啊,但是这种算法的话呢,我不知道他是不是足够鲁棒,如果啊就是假如黑客黑客的话,是不是有可能也可以攻击进去,如果黑客不能攻击进去的话,那确实是可以实现。
我们讲的那种战争迷雾的效果,而且也不怕别人的外挂,ok好,第二个问题是什么啊,第二个问题很有意思啊,同学问我说暴击不能在服务器算好,就发给客户端嘛啊这句话呢其实是对的,为什么呢,这取决于你用的什么同步。
比如说你如果用staff shot同步,或者说state同步的话,大概率这个暴击是在那个服务器端算的,但是其实今天我们我们讲的有一个细节,就是说其实在状态同步里面。
就states connection里面的话,有一个方法,就是我们如果能保证,那个服务器和客户端的随机数一致的时候,有的时候我们可以允许客户端预测,自己触发了暴击,这个时候呢先把ui打出来,让你爽到。
然后过一会儿服务器那边再给你确认一下,当然了,这里面你如果自己写个,自己骗自己的作弊器也是可以的。
但是呢对于真同步来讲的话呢,啊,那应该基本上都是在这个客户端自己算的,而且我要保证算的是一致的对吧,那服务器没必要再算一次,但是我们讲的生动部里面还有一种实现,就是说其实服务器那边。
我也模拟了一整套状态,那他其实呢只是做一个校验的作用,没有必要把这个状态在反向的同步,也和无端,因为这样的话实际上啊它就没有必要,因为输入是一样的话,产出应该也是一模一样的对。
所以这取决于你用的是哪种同步策略,如果你用的staff shot,sychization或者csonzation的话呢,一般来讲是服务器算出来的,特别是暴击这种对吧,高度结算敏感性的这样的一个业务。
它一定是在服务器算比较安全一点,哇这个这个问题就比较挑战了,他问我说,语音游戏和快照同步有哪些区别啊,首先这个语音游戏的引擎架构,现在还是个open question,就是说大家有很多的流派的讨论。
所以呃怎么说呢,就是如果你让我去拍脑袋去想一下,就是未来完全跑在云端的这样一个,online的世界的话,我还觉得他真的有可能像快照那样的,一个世界,就是说其实我只是在那个服务器端。
模拟一个one universe对吧,所有的客户端只是观察这个世界的窗口,你看到的只是一个有限状态的一个同步,那这里面的话呢,最狠的就是说连渲染都不用你渲染了,我直接推流下去。
你看到我的这个视频就好了对吧,可以一个互动的一个视频,那就这次云游戏最经典的概念,那如果再狠一点的话呢,就或者说我做的更多一点,实际上是我是把这个世界结算好的状态,反向的推下去,在客户端那边的话。
还是构建一个这个世界的subset,然后渲染出来给你看对吧,那是第二种选项,所以说我觉得确实跟快照的基础思想,是有点像的,你看如果这件事情假设真的成立啊,我觉得这个啊camark还是很厉害的。
总是在旋转的,对不对,然后螺旋上升,说不定过了30年后,诶,我们的快照的这个sima zation,又会成为下一代这个云游戏引擎的,这个主流架构了对吧,也是有可能的,ok好的。
那要不今天那个我们先到这儿,今天的话就是我们把网络的基础,那给大家分享了,那下一节课的话呢,我们就讲一些网络游戏的,更高级的一些功能,好的谢谢大家。
19.时域调制 (II) | GAMES204-计算成像 - P1 - GAMES-Webinar - BV1d8411V7ZT
我们再稍微等一下这些同学们。
这个给我们带来了几十年的一个深远影响啊,这个是啊对大家整个生活呀,或者是经济形势都有一个非常积极的影响哈,这个可能大家比较年轻,没有感受到这个时代的一个变化,但我们这一代人士都深深切切的感受到了。
带来的一个不断的高速发展,好啊,时间到了,就今天我们给大家定正式开讲一个新的课堂啊,这我们temple,temporal encoding的第二课叫nonset mei,也就是大家所说的一个非视域成像。
上节课给大家讲到了啊,我们这个director timer flat image,我们上课讲到了几个核心的几个点哈,我们是通过两种思想啊,第一种思想就是street cam那种。
我们可以通过牺牲一个空间分辨率,来换取时间分辨率的这么一种做法,第二种就是像啊tcs p c spy的成像里面,我是通过牺牲一个时间维度,就是通过时间来换时间精度,重复测量来换时间精度。
哎就是以时间换时间的这么一种思想啊,就通过这两种思想,我们可以到皮秒甚至是亚皮秒的一个啊,测量精度,今天呢我们是基于上节课的一个direct time flag,image啊,给他一个应用。
呃其实本身这个nononsentimeting啊,不只是可以用这种pose的这种方法也可以做好,这个也是嗯可以通过这个continuous wave,tea flight来实现的。
呃这个我想那我们讲到哦,这节课首先覆盖的还是一个direct time flaimage,来实现这个非视域成像,后面的话我会想有时间的话可以给大家讲一下。
我们如何通过一个简单的便宜的这个continue,wave的一个top相机来实现我们的非智与成像,它是一个通过扫频扫向的方式来构建一个嗯,image formation model啊。
最后来把它这个正向的模型,然后写出来之后,我再通过一个dm去把它给解出来哈,这个也是可以实现的。
今天啊首先给大家讲到的是一个,什么是非实际成像,我们是怎么样实现这个非式与成像的呢,啊然后再给大家讲一下这个啊,nonset mage的一个image formation model。
我们这个怎么样来描述这个成像的过程啊,其实像我们嗯之前上课,从最开始的一个像嗯人眼的分析啊,呃相机模型啊,最后再到相差噪声,其实呃前面的一些课程,是给大家做一个成像系统的描述。
因为我们最后要构建这个嗯系统,求解的一个优化问题,我首先要把这个系统描述出来,诶,描述出来这个图像系统之后,哎我们就可以解,通过这个已经描述出来的方程来解,我们想要知道的一个未知量啊。
这个思想就在我们这整个课程设计的时候,就已经体现出来了,到今天就嗯以大家一些实例哈,因为这formulation model最后解出来,它也给大家一个实战的一个机会,嗯因为像我们刚才讲到了。
我们这个null set没经过嗯,一个一次发射反射再反射再反射再回来,哎这总共是一个啊五个维度的一个传播方程诶,这个时候对我们实际的想捕获这个非视域成像,是非常困难的,我们要解了一个五维的一个dq 5。
你想这个这是多大的一个这个方程啊,是不是这个就非常困难,后来呢就是mo two就是一个师兄啊,后来在斯坦福发了一篇nature,就搞了一个confocal nonsite mei。
这个我可以给大家详细的讲到哎,这个什么是cfocal啊,后面呢呃我们会发现我们在这个墙上测到了,这个是呃d等于零的一个位置,我们是,但是我们是要实际想要测到的,这个呃墙后面的一个三维物体。
是一个t等于零的一个位置,我们通过一个波动方程啊,来把这个整个f k k就是frequency the wave number,两个之间建立一个关系,来整个做一个迁移,来最后来实现一个啊。
通过一个叫sk migration的一种方法,来把这个后面的一个墙,后面的一个三维物体重叠出来哈,这个就是今天大概主要覆盖到的内容,诶这个首先就是什么是非视域成像呢,大家想一想这个问题啊,非世玉啊。
从这个名字来说,就是诶我本身我自个儿看不见他,它是藏在一个墙后面的一个东西是吧,其实有时候也叫looking around the corner,这个场景是这样的,我们这是呃,我们这边有一个激光啊。
激光,然后在激光旁边是放着我们的相机,这个放着我们放着我们的相机,这个激光发射这么一个点光源啊,或者一线光源,我们这里以点为举例吧,一点光源达到这个diffusion的一个过程,这里有物体啊。
被一个墙挡住了,我是想通过这个上面这个decision wa,通过这里面的漫反射信息,来恢复出来我们最后的一个呃,墙后面的一个场景是什么样子,大家我们可以看到哈,激光发射到达这个墙面是第一次传播。
他这是第一次的传播方程,我这一个点呢,然后又啊变成一个球面波哈,这个点发出球面波诶,每一个球面波又开始往外往外传播,这是第二次,然后呢,这个这也是这被墙漫反射的波,然后打到这个物体表面,物体表面诶。
每个点又产生一个球面波,对不对,然后到达这个墙,这是123对吧,到了这个墙啊,这个反射,呃问题本身反射已经是第三次的变化了哈,然后再到啊强就算是第四次的一个反射,这个墙再经过一个到达detection。
总共是带一个五维的一个方程号,就在我们墙上所观测到的呢,实际上是这个物体表面,这是我在我墙上的一个呃点了这一个位置,对不对,取其中一个像素,取出一个像素。
我去分析它的一个呃时域的一个time his gram,大家想象一下,这个我在墙上看到了这个球面波的叠加,我他这个点的黑gram,它具有什么意义呢,对不对,其实嗯可以想象一下我们最短的一个路径。
最短的一个路径哈,就是我最前面这个他们cos的最前面这个音,实际上就是我真实的一个三维物体的一个信号,的一个问题,对不对,大家可以仔细的斟酌一下,这个几次反射带过来什么样的影响。
当我们在正式讲这个nl 3 min之前,要给大家掰扯一下,这个非视域成像到底有哪些难点,首先呢我们知道啊,我们的一个光强哈,特别是呃一个像那种球面波,我的一个光强是随着r方分之一。
也就是距离平方分之一哎来去衰减了,对不对,然后我经过两次墙面的一个defi,再加上物体表面的一个def,我这个最后有三次的一个scattering,对不对,这个时候他衰减的速度是远远大于这个。
随着平方向衰减的一个速度的,对不对,也就是我们一束激光打到墙面上,然后最后再经过墙面的一个散射,再经过物体的散射,再经过墙面的散射,这个时候能够到达我们的一个传感器,的一个光子数是非常少的。
也就是说我们现在啊,实际上能探测到的有效信号它是非常微弱的,这个时候就给大家带来了挑战,给大家带来的挑战,说一般我们是用一些单光子器件啊,下面spd传感器啊,或者换台卫生管来实现嗯这么一个高速呃。
微弱的一个测量,这个它的一个solution通常就是非常高的一个hdr,或者一个git single for tdetector,诶这个是第一个挑战哈,第二个挑战呢。
就是本身它是一个非常eu condition的一个inverse,problem,我们要恢复墙后面的一个三维的一个场景,就我们不知道嘛,最后拿到的是一系列一个球面波的一个叠加哈,而且是经过叠加在弹射啊。
这个时候整个一个这个是变成uu,condition的一个问题,这个是怎么解决呢,一般我们是首先我们需要有一个,皮秒量级的一个时间分辨率啊,时间分率,我们可以解析我们这个波前的一个下位。
那第二个呢就是我们用一些像数学的一个,先验知识,或者是一个呃图像的一个先验知识,来做一个啊upose的一个约束哈,嗯或者是应用一些其他,unconventional的一些approach。
比如说后面我们讲到一个fk migration本身呢,第三个挑战是啥呢,第三个挑战就是我们这个要求的一个逆问题啊,是非常巨大的一个matrix,我们经过几次传播,我们会拿到一个五维的一个向量哈。
五维的一个向量,这个数据量是非常庞大的,所以说呢,我们需要一些构建一些新型的一些算法呀,或者是一些新型的set up来解决这个效率的问题,这个时候人聪明的。
人类就发现了一个comfortable的一个问题,我把这个反射区的一个pad跟回来的pass相重叠哈,这个就可以啊,实现这个问题的一个客服啊,总之哈我们是要实现一个非视域成像,面临的三大挑战。
首先b信号很微弱,第二就是它是一个airpods的问题,第三就是我们这个啊matrix managment,是非常大的一个managment。
这是一个呃最早的一个呃,looking around the corner的一个工作啊,这个是应该是mit啊,这是welton,就是在welton在ross卡组里做的一个工作,诶。
这个时候我们可以看到诶,直接的一个managment by project intensity,诶,跟最后recover的一个这个一个图像啊。
这个是怎么实现的呢,我们那个时候我们通常是用一个啊,gao来做扫描,gao来做扫描,哎,来每个点在墙上不断的去扫,然后去恢复出来,这个回拨完,最后通过一个高时间分辨率的一个一个detector。
来把这个拨弦重建出来,然后呢,后来就是因为这种方法就比较比较老笨哈,做了一个呃这个nonset min setup,这是一个线扫描的,一个可以做到每秒一帧左右的一个呃,一个那个时间分辨率哈。
这个是速度呃,这个帧率就比较快的哈。
然后呢呃讲了这个那什么是非视域成像,接下来要给大家啊,从这个源头分析一下,我们这个非视域成像的一个基本模型哈,通过构建这个基本模型,会让大家理解这个非区域成像是怎么实现的,然后我们去怎么提升。
这个非日语成像的一个系统。
一。
这个大家都播放了啊。
首先呢我们可以看到我们的一个,light source跟这个sensor我们共用一套光路哈,然后通过一套gvg在x y方向去扫描啊,去扫描,然后这个光呢经过这个经过这个咖附近。
去打到这个decision的一个墙面上,decision的一个墙面上,然后呢在defuse到我们这个后面的一个objects,对吧,这个时候我们再通过一个,比如说我们要再回到这个pass。
这个这个这个小body哈,body再反射出来这个光,再回到我们的detector,这个时候呢我们在我们的一个传感器上,就拿到了一个这么一个his time,his gram。
这个time his grand就分为两个部分,第一个部分就是我们的一个啊,直接就是直接一个direct reflection,就是我们刚开始达到那个点的一个,direct reflection。
然后第二个呢就是一个inner,发音是我们最后想要测到的信号哈,我们通过不断的做三维扫描诶,把这个indireflection提取出来,这个时候嗯就是一个就是一个,这个时候就是一个那个完整的一个构建。
一个完整的信号哈,就是通过二维扫啊,这同学问的什么叫ga镜,那不叫ga叫jo g a l v o啊,那个g a l v v那个是嗯,就是一个扫描的一个镜子哈,你可以理解为可以xy扫描的一个镜子。
按角度扫描的一个镜子,这干活镜啊,这个是啊,我来给大家科普一下哈,这gao镜是可以实现一个比较高精度的一个角,度扫描了一个七点,然后更精确一点的一个叫pizj p o,就是通过嗯这个苹果就是压电。
就是压电效应哈,我们不同的电压来产生不一样的一个位移哈,或者是就是拿到rap这种高精度的一些嗯,微操作的一些台面上来使用的一些技术,这个把这些gb镜啊,这个时候是已经拿出来做一个扫描用哈。
诶我们实际上我们可以看到的,就是当我们的laser点上,然后这是我们的一个探测的一个点上,就是传统的一个呃,none of that meeting,他是一个non computer的sample。
就是我们的这个激光打过去,这个点给我们测量这个点哈,它不是重叠的,不是重叠的,这个时候在我们detection上观测到了一个,观测到了一个time his gram,就是啊这么一种情况就是很大。
然后再衰减n有个信号,然后在不断衰减,这个是nonconforcl的一个supreme,这个时候我们啊,光光线传播会有非常多的维度哈,这个时候大家不是很喜欢,因为维度太高了。
对我们计算来说是有非常大的压力的哈,非常大的压力,这个是怎么办呢。
这mc o two就搞了一种叫comfort的一种办法,也就是我们最后测量的时候,我不把这个测量点跟这个激光点分开,我就把这个测量点跟激光点去重合诶,这个时候我们就发现这个激光点,激光照亮这个点。
它在反射出来一个球面波,打到这个物体表面,这个物体表面再反射回来,再反射回来了一个球面波诶,又会达到这个点,就是这两个light path就重合了,实际上我们最后拿到一个五维的一个这个dlc。
我就变成一个三维了,因为我们其中两个维度已经相互cans掉了啊,相互看透掉了,这个时候我们就发现我们实际要解决的问题,仅仅是一个简单的一个,three d d convolution的一个问题。
这个就变得非常有趣非常有趣啊。
而且可以极大的提高我们这个啊,nonset mage的一个效率哈,啊这是一个the same path to the object,就是我们这个光来回的这个路径是一样的啊。
这个时候也叫convocal sai,在cfl 30会有什么问题呢,csol one sam本身啊,他那个光啊,实际上是会受到这个,就本身照明那个激光的一个点的影响,这个时候我们就需要一个git的办法。
这滤掉就滤掉,这个时候就要求我们的器件会比较快哈,当然啊,现在今天的器件已经完全可以达到,这种confil的一个set up,我们这个时候通过这个comfort的办法,就是带来了两个好处。
第一个就是我们两个来回的一个life path重合了,极大的简化了,就从五维一个问题简化到一个三维的一个测量,哎,同时因为我们这个维度维度的减少,我们可以极大的提高,我们这个非智与成像的一个效率啊。
实际上到最后我们啊,就只是仅仅是做了一个sdd tion啊,就可以实现我们这个分式与成像。
这是一个console的一个呃,就是set up,哎,我们通过每次测量这么一个点,然后在这个xy撇y x撇,y撇这个二维的一个地方做扫描诶,每次我们一个点是一个拿了一个time his gram。
对不对,然后我在这个x撇y撇两个方向分别进行扫描,诶,就可以拿到了一个x撇,y撇t的一个3d的一个data q啊,3d的一个dq 5,最后我们就拿到了一个三维的一个measurement。
实际上我们是呃很简单,就是拿到了一个三维management,我们把这个三维的managment记为套啊,它是一个有关于x撇,y撇和t的一个啊三维的一个测量。
唉这个时候让我们来正式的去写一下,我们这个image formation model,本身呢我们知道我们这个时候,我们的一个测量哈,它是一个三个维度的,就是要买什么,我们知道x撇y撇t对吧。
我们的transport matrix,我们可以知道这个我给大家画一下啊,我们来本身的这个transport matrix,sorry我给大家直接在这个上面画一下,这个画一下会更清晰一点哈。
我们可以看到诶,换个颜色吧,对,诶这个时候光第一次发射,诶第二次反射,啊被物体表面诶再来一次,一般是再来一次反射哈,这个就是,第一次123,四五,然后六一,三,四六总共是经过了一个六维的一个。
transform matrix,然后我们要重建的呢,重建实际上是重建我们最后的一个,x,t的一个data cube,它是一个三维的一个data cube,这个时候遇到问题。
这是一个传统的一个none of smain model,我们这个时候就可以看到这个transport matrix,我们经过几次传播哎,加上反射呀,加上cheering啊。
它是一个非常非常大的一个matrix哈,比如说我举个例子哈,比如说我们要仅仅测量100个点的时候,我们就会有一个啊train的一个elements,我们这个要是1000个点呢。
我用spss h做了一个representation的时候,它就需要一个p p t bt,一个就是一个memory才可以装得下,这么大的一个传送文matrix,这是对大家来说是非常难以处理的。
这么大一个超行去超巨大的一个方程哈,就是哪怕我们是用一些matrix three,像卷积啊来做也是非常困难哈,这时候我们最早的像valon啊,像嗯bot sava 15年的工作。
他整个的一个计算的工作量,都在一个n的五次方这么一个维度上,memory消耗呢也到了一个n的三次方,那个时候大家啊经过这么多一个测量,他可能当时测光测就测个几个小时哈。
最后通过一个解个十分钟才能把这个match解出来,然后呢直接做这个interactive inversion,这个也是需要这个五个维度的一个呃,五个五个维度的一个测量,当然这个时候嗯。
当时head用的是一个etf来实现了一个,用了一个etf来实现了一个啊这个null set成像啊,这个维度也是非常高的,所以说那个时候无论是采集还是到计算,我们都会花花非常多的一个时间啊。
来才能实现这么一个非视域的一个成像,所以说对我们来说,这个整个东西就是一个非常难以计算的,这么一个超大的一个matrix,所以说呢这个18年的时候。
这个mac o two就搞了一个convocncmei,这个我们呈现的模型呢,我们刚才讲到了呃,我们刚开始上课,讲到了这个,x y x撇y撇p撇的一个measurement,哎这个就是fish,本身呢。
我最后因为是cfo的一个模型,我就可以每个拨弦哈,它是这样,就一个3d的一个black ko 3 d blolo啊,这个也会变得非常简单,大家发现了吗,这个时候我们要解决一个问题啊。
实际就是一个3d的一个d convolution,这个就变得非常简单,无论是从我们set up来说,还是到我们最后的系统理解来说,还是到我们最后把这个东西解出来,说,我们仅仅要解的就是一个3d的。
一个节卷机的一个问题,这个时候呢我们的整个计算的一个量,就到了一个n3 log n的一个情况,mary consumption也是只是n的三次方诶,这个时候也可以实现接近的一个real time。
当时啊我们这个当时发完nt之后啊,这个mate也把这个套系统拉到了,这个cpr的现场啊,当然也可能18年3年考cpr的那个同学们,可能会对这个有印象哈,在现场展示了这个非视域成像的一个。
实时的一个重建哈,当然这个时候我们都是基于假说的,就是一个我们这个scattering的一个medium,都是一个呃各项同性的一个scattery哈,没有考虑像嗯这种表表面的一些小经历啊。
或者是这种镜面的一些反射啊,没有考虑这些问题,这个时候我这个共聚焦的一个扫描呢,然后就会获得这个x撇y撇,p撇的这么一个madam,实际上就是一系列的拨弦的叠加。
我们最后拿到的信号就是一系列拨弦的叠加啊,唉我们要实现这个恢复,我们第一步就是要对它进行重采样,然后在我们那个t的时间轴上啊进行一个停留,因为我们知道他整个播前啊,第一个拨弦中心的第一个点。
实际上就是我们想要的信号,但是现在都是叠加在一起了,所以第一步我们是做了一个嗯,resample跟attenuation啊,然后我们这个completion kernel呢,基本上就是已知的哈。
我们可以直接测量这个diffusion wall啊,来把这个conversion kerne诶,这个写错了,不好意思,ctrl的kd来这个直接的展示出来,这个时候我们把这个resample的一个信号。
直接进行一个呃deconvolution啊,我们就可以很快速的恢复出来,这个我们的target,就是x y u这么一个三维的一个target,诶那不好意思,刚才这个把信号断了哈。
这个时候第一步实际上就是resample和tedation,along tx对吧,我们知道这个信号的第一个位置哈,信号第一个位置,实际上就是我们信号那个地方啊。
本身呢一个conclusion kernel啊,他就是啊,他就是可以直接通过测量或者是仿真,都可以得到哈,这conclusion kne把他这个做成一个inverse filtering。
作为一个dd conclusion哎,就可以直接恢复出来,我们想要的一个xyu的一个三维的一个信号,这个是可以呃,非常简单轻松的来获取,我们这个嗯nonset amazing,这个是一个巨大的进步。
从此之后啊,这个非实际成像啊,就慢慢看到了,有实际应用的可能性,因为我们真的可以把这个问题简化到,一个简单的一个3d的一个抵抗motion,诶,最后我们再呃,通过这个resample。
就可以直接拿到这个x y z的一个,三维的一个图像啊。
这个是可以变得非常快速而且清晰,这是当时啊他们做了一个实验哈,这个分辨率是64x64,然后整个曝光的时间只需要0。1秒哈,这个我们可以看到back projection的一个方法。
我们可以可以这个很难看到里面是啥,然后用future back projection呢,也是很难恢复出这个三维形貌啊,就可以用l c t的啊方法去进行恢复。
然后或者是我们做deconversation的时候,再加一个约束,就可以更好的恢复我们这个想要的信号。
这个是我们恢复出来的一些结果。
但到了后来哈,人们还是不能满足这个重建的结果,到了19年srah的时候啊,这个斯坦福的一个golden也是我师兄啊,他们组里就做了一个frequency web number。
也就是从频率到波数的一个迁移的一种办法,来实现一个啊高速,然后高质量的一个啊非视域成像,这个sk migration本身,这个思想是从这个通信领域借鉴过来的哈,通信领域借鉴过来也是从电也是分。
可以说是从电磁波领域借鉴过来的,那首先呢我们可以回顾一下,我们物理学里面的这个波动方程啊,就在我们的一个自由空间里面,我们这个波的一个方程,还有波的传播,在自由空间里面的传播。
也可以通过这个rf round平方,等于y减去个c方分之一,然后right方跟run t这么一个约束,我们这是我们的波动方程,我们的任务是什么呢,我们要测量的东西是在这个墙面反射过来的。
我们需要把这个boundary condition,也就是在z等于零,也就是在墙面上,我们可以认为是z等于零,然后迁移到另一个bug condition,我们通过这个波动方程来迁移到另一个帮助。
condition,也就是t等于零的情况下,t等于零上,实际上就是这个信号本身的一个,表面的一个东西。
所以这是一个呃本身它的一个set up。
这个时候我们的image formation model变成什么呢,我们它的一个本身,我们这个波传播的一个方程啊,就记为f然后x z t哈,我就记为简单记为fx z t啊,我们这个强啊。
我们就设为z等于零这个位置哈,然后呢我们confer measurement,实际上就是我们要直接在这个墙上,测量的这么一个位置,也就confile manager呢实际上就是z等于零的一种情况。
当我们要借助这个波动方程,来把这个z等于零哎,迁移到这个t等于零的情况下,就可以复制出来这个bu表面,一个三维三维表面的一个形态啊,这是我们的一个comforty minimal。
它实际上就是一系列的一个波形的叠加,方波形的叠加。
本身呢就是我们要解决这个问题,还是比较困难的,所以说啊大家学过物理的同学,也就是我们说说f c d e啊,我们通过啊,这个对波动方程进行有限元的一个差分啊,我们知道啊。
刚才我们可以已经知道了这个波动方程哈,波动方程是这样的啊,混合方程式,sorry,这是v哈,我步骤方程实际上是这样的,这个时候我们想要得到这个参数,这个参数我们是可以通过有限差分的方法。
因为我们这个managment是已知的,我们是通过这种有限元的方法来,可以来逐步的获取我们这个round five比rt是什么,这是获取这个five的一个完整的一个方程哈。
然后我们就可以通过不断的迭代哎,通过前面的一个step不断测量迭代,然后去update这个fine,在这所有的一个great cell来after you define。
当然我们这个时候通过这种测量方法,是非常慢的,非常慢的,我们要通过不断的有限源差分分析,不断的迭代来去啊,恢复我们最后表面的三维形貌,最后实际上跟扫描也差不太多哈,差不太多,这个时候大家不喜欢怎么办呢。
我们现在我们的task呀,实际上就是想做了一个frequency wave的一个迁移,我们是想要把从频域从频率迁到了一个view number,上面一个问题。
也就是把我们的帮助condition从z等于零,变成t等于零啊,这个过程哈,这个大家可以简单的想一想,我们这个我们要实现这个帮助condition的迁移啊,首先我们第一步要做的事情是什么。
大家有没有这种感觉哈,就是要我们要知道这个实际上要做的。
这个事情是什么哈,就是我们从这个bug condition z等于零,哎我们变换到这个bug condition t等于零这种情况,这个时候大家怎么做呢,怎么做呢。
这个时候就有非常关键的一个点哈,来首先还是从一个set up来给大家,先把这个过程先讲明白好,还是我们传统的set up,这个是这个时候我们可以右右边看到。
我们有很多诶这个cfo management啊对吧,这个时候我们是已经得到了,这个d z等于零的这么一个信号,z等于零的x y t的一个management。
但是我实际的一个managment是比较弱的哈,这个是我们刚才那个是我们恢复出来的。
这整个的一个从频率到波数的一个迁移,是怎么搞的呢,我们的这个测量到这个场fxy t是我的magiment,因为这个时候我们的z等于零的这一个,fix y t哈,首先呢我们要把它变到频域啊,把它变到频域。
这个时候我们就得到波数kx,波数k y跟我们的一个频率f对不对,这是我们的第一个频率,然后我们再在这个频率里面,这个我们叫做fb,我们在在这个频里面进行一个spectrum的一个。
interpolation,我们把这个频率啊,频率就是这个f这个地方,也就是这个f我们要迁移到在第三个波数上,也就是大家所谓的f k migration哈,这个f k memory的一个迁移的过程。
然后我们再通过一个e的一个分裂变换,再把它变到我们的一个新的一个,关于f的一个方程哈,就是关于也就是t等于零,这个时候就可以把这个fx 2 z的一,个波数解出来,实际上就是我们要最后想要解到了一个。
三维空间中的一个信号,好最后这个sk migration的一个过程是什么呢,首先我们要把这整个的一个波动方程,要把它搞出来哈,波动方程要搞出来,我们要因为这个波动方程本身是关于这个。
xyz跟t的一个函数哈,我们怎么样通过我们测量到的一个呃信号好,我们测量首先测量的信号是fxy,我们要把这个信号诶变过来对吧,本身呢我们可以看到这个把它变到平,这个实际上是对这个频谱的一个变化哈。
实际上也就是我们所说的一个f f t哈,这是我们的一个频谱,我们这个频谱是关于是有关xyz,还有t的一个函数x y z t的一个函数,我们怎么样实现这个从f到k的一个迁移呢。
首先我们要对这个这个函数这个式子里面,这个t把这个t设为零啊,把这个t设为零设为零之后呢,我们就可以把这个函数这一项简化掉,这一项简化掉,我们就得到了一个fxy t,fx y z t等于零的一个函数。
这个时候实际上就是我这个spectrum,k x k y k f,然后对ksk y k z这个波束上的一个积分,这个时候我们还是没有完成,从f到k z的一个迁移,对不对。
我们这个我们时刻牢记我们的使命哈,我要每刻要牢记我们的使命,是要实现从f到k z的一个迁移哈,怎么签怎么办呢,这个我们继续,我们这个时候因为我们刚才讲到了,我们要实现从f到kz的一个迁移,对不对。
这个时候我们就可以用到物理学里面,一个叫色散方程的一个东西啊,色彩方程也就是f我们要换元啊,对这个对这个式子进行换元,f就等于一个v,然后根号下k x k y k z的平方啊。
在这个里面k x y已经是啊,我们知道这个时候已经等于零了哈,实际上因为他这个confil的一个过程啊,它是一个去的一个path跟回来的pass是相符,overlap,这个时候我们就可以诶。
对这个f进行一个替换啊,直接进行一个替换,当然这个时候就带了一个v哈,f这个时候我们要把这个k z替换掉呢,实际上就是也很简单对吧,我们最后fk x k y k z实际上就是v k z啊。
这个这个是我们加了一个绝对值符号,是因为我们不知道这个解了这个平方之后,是不是啊还一样啊,这个时候实际上就是我们的这个,kz,build up的这啊f k s k y k z,跟这个f撇的一个关系哈。
这是首先就是f啊f,用这个新的一个式子来表示哈,诶,这个时候我们就可以,对上面这个式子来实现换元,把他这个地方来实现换元,这个方法呢是叫george提出来,这是还是还不是挺远挺远的。
这是2000几年叫还是199几年,这个叫gorge,提出了一个叫scout interlation的一种办法,我们来实现这个对这个频谱,k x k k k y f这么一个方程进行换元哈。
换完之后我们就拿到了这个five,关于,x y t的一个方程,实际上我们可以看到,通过这个啊dispersion relationship,我们拿到了实现了对f对k z的一个迁移哈。
我们本身我们的频谱信号,频谱信号,拼图信号f撇啊,fib啊,k x k y,来实现对这个fk x k z,k y k z的一个迁移哈,这个时候我们通过这个scout interlation啊。
来实现了啊,对我们这个频谱的一个重采样,对啊,这个实际上也就是对我们这个f,把它变换成k z了啊,总是对频谱的进行冲采药,这个时候我们就完成了,从频率到波束的一个迁移,好到波数的一个迁移。
大家可以看到我这个整个迁移的一个结果,就基本上就是一个inverse的一个分列变换,就是一个逆的一个数列变换了,对我们通过t完之后,实际上本身呢这个算法就变得非常简单,第一步f f t把它变成频谱。
然后通过一个sk migration,然后里面很重要的是一个叫scout,one day interpolation的一个办法,然后再把它做一个简单的一个逆列变换诶,这个时候就可以非常轻松地获取一个。
我记得上大学的时候,老师就讲过哈,这个十余里干不好的事呢,大家就放平日里看诶,这频域里干不好的事呢,大家就放到十余里去干,这个时候就会往往算一个呃域哈,就可以比较好的解到一个呃这种结果。
这个时候我们就实现了,从t到从z等于零到t等于零的一个迁移,我们就可以很轻松的获取,我们就是物体表面的一个波前的信息,来重建这个物体表面的一个三维结构,这是我们整个fk mhy的一个伪代码哈,首先呢。
也就是我们对我们的信号,进行一个简单的预处理啊,就做一些简单的ping啊,诶,然后这个时候再对我们的一个信号,进行一个快速的分裂变换,我们就拿到了一个关于fibk x,我们可以看到这个地方。
就是这是我们拿到了第一个挺好,我们这个时候要把这个f迁移到k z,f迁移到k z,然后呢通过这么一个简单的一个嗯叫stolation哈,我们就可以对在频谱里面,对我们的信号进行了一个重新的采样哈。
来实现f对k z的一个迁移,然后再做一个简单的一个inverse fly变换诶,再安排一下,在post processing下,就可以快速的恢复,我们这个f关于x y z的一个场,其实这两个问题啊。
从convocal native setting mage到我们的fk migration,整个的思想都是对这个问题进行简化,我们看到它里面操作也不多,前面一个confusion 3里面。
把问题简化成一个3d conclusion啊,这个问题就把问题简化到了一个呃,在评语里面做一个简单的一个重采药哈,这个大家就会发现诶,这个问题原来是这么的简单哈。
这是一个呃当时拍摄的一个结果,这个曝光时间是挺长的哈,大家这个可能踩了,当时踩了有180分钟,三个小时,然后呢这个算是也挺快啊,90分钟就把这个migration给算完了。
就是啊一个confession confession,这是一个back projection的一个结果,也就是啊当年是welton那种哪里if的一个做法啊。
back projection filter一下,这个是通过african migration来实现的一种办法,所以大家会发现这个对以前的办法,有一个长足的一个清晰的进步啊。
我们这周围这些杂散光基本上都给去掉了。
基本上都给去掉了,然后下面呢再给大家介绍一下其他的work,这是2020年啊,要等人搞了一个direct like home transform,这是我们藏到后面的一个场景。
这是一个recover的一个surface,后来呢这个method呢,这这这几个老哥又把这个非视域成像,又拓展了一下哈,这个是直接就搞到锁孔里面去了,这个大家知道大家开门还是挺不容易的哈,这大灰狼来了。
这很难让大家开门,这我干脆就直接一个激光通过这个锁孔打进去,来看到你这个房间里面到底是什么个样子哈,这种就把这个我问题变得很实际哈,我们的大家这个大家锁里面都有锁孔,锁孔是可以透光的。
我们是可以通过这个锁孔,来把这个里面的三维形貌来做一个窥探啊,窥探啊,这是当时啊恢复出来一个结果啊,虽然这结果会比较差哈,因为我们set up是比较econdition的,会比较差。
但是诶这个也是告诉大家,哪怕你藏在这个屋里,也是可以看到那里面到底发生在什么的,今天呢就给大家讲了一下什么是非视域成像,然后给大家讲了一下,传统的一个非视域成像的model哈。
我们的一个transport matrix是一个呃,就像蓝衣服的一个setup,就是一个六维的一个matrix,我们传播呢啊就是最后一个managment,是一个五维的一个managment。
这个时候就变得非常困难,所以说啊,18年macbook to就搞了一个confucnasset mage,把其中的一个墙面照亮,那个物体的一个life path,跟物体反射回来。
life path所重合时间,就把维五维度变成一个三个维度的一个managment,实际上我们要解的问题就变成一个简单的一个,sdd convolution的问题。
再后来呢我们就要通过一个波动方程的方法来,通过这对这个frequency到wave number的一个迁移,来实现一个呃frequency到wave的一个迁移。
来实现一个帮助condition t等于零到帮助condition,帮助condition z等于零到我们帮助condition啊,t等于零的这么一个啊搬迁哈。
这个时候我们就可以因为这个rt等于零的位置,就是我们实际物体表面反射波前的一个,三维形貌的一个位置,哈哈这个是大家就可以直接重建出来,这个三维的一个结果。
这个light com transform这篇文章我没看好,这个我还没真没怎么看,这个文章应该是,应该是也是一个setup,应该是都是一样的哈,这个具体是怎么做的,我没仔细看。
大家可以有兴趣可以看一下啊,好今天的课程就到这里啊,同学们有什么疑问的话,诶可以啊,直接在这直播间里去问啊,今天这个是临时加了一节课,可能做的会比较短哈,因为这个本来这节课是想讲这个。
当然同学们就可能比较想听这个,非斥与成像的一个东西啊,实际上啊,一非是与城墙这个东西实际上是比较简单的哈,就比其他课题会简单很多,只是他设计一些嗯要快速的测量啊,这个做实验可能会不好做啊,会不好做。
就从原理上来说是非常简单了,空间分辨率这个起码得有几十乘几十吧,这个空间分辨率这个主要看你要测量时间,你要想测的点多了,其实就可以快很多啊,就可以就点少就快很多,点多的话嗯,那就卖了,这个没办法。
这个就是跟你测量的一个点的速度有关,这个一般大家就测个可能64x64啊,这么一个64x64是多少个点,六六三十六,3600多个点,同学们还有问题吗,好现在同学没问题了哈,再次感谢大家来到gx 204嗯。
今天是给大家插播的一节课哈,这个嗯,同学们也是对这个分析成像,有一定的一个认识啊,好再次感谢大家,今天的课程就到这里。
19.网络游戏的进阶架构 (Part 1) | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV13B4y1L7bZ
Hello,大家好,欢迎大家回到games104,现在游戏引擎的理论与实践,我是王希,然后今天开始我们的第19讲,那么在开奖之前的话,大家有没有注意到今天我有什么区别对吧,大家看看我今天穿的什么。
对我们的社区的T恤终于印出来了,这个我还我今天还特别高兴,因为课程准备到最后几分钟的时候,课程组告诉我说我们的T恤已经印出来了,所以我迫不及待的就穿上去了,给大家看一看,大家觉得效果怎么样。
看看自己还不错吧,然后那个我们那个课程组的小伙伴的话,会尽快安排给我们的,就是所有被抽中的同学,还有我们社群的热心的同学们,还有什么,还有我们作业做得非常那个好的,同学都给大家寄过去。
大家还记得上节课我们讲过,就是说作业中的话,大家只要做完两个作业的话,我们就会把T恤送给大家,因为也是想鼓励大家,一起去参与到我们的课程中来,说实话啊,我们也不知道有什么目的,反正我觉得能跟着我们一起。
把这个课程跟到现在的同学都是好汉,因为我自己想了一下,我们的课程现在总时长已经接近50个小时了,然后我觉得我在大学读书的时候,让我一个学期上一门课,我有的时候还很难坚持不逃课。
所以说我觉得能坚持下来的都是很厉害的,这个选手,那么其实呢说实话,我们自从那个就是上几节课,说鼓励大家在我们的B站上面去留言的时候,其实收到了很多很多大家的声音,真的很感动,有的时候我们很enjoy。
看大家跟我们讲什么东西,确实特别让我有感触的是,说一其实准备这个课的话,我们蛮辛苦的,然后我每天都在想要争取下一周不上课,我又可以偷懒了,但是的话呢真的到临近尾声的时候,还真的有点舍不得说。
哎呀我每个星期能跟大家打个招呼,告诉大家我们学的一些东西,想要一些东西,好像已经成为了我们生活的一种习惯,所以的话呢呃我我我们也在想说,后面怎么样子能够继续帮助到大家,这里面。
我就想正好跟大家好长时间没有讲一件事情,就是说那个大家我们好久没有讲,我们的PICO引擎了,实际上的话呢,最近整个课程组在非常忙的准备课件,但是的话呢我们那个忘了,这个就是说呃跟大家讲皮克罗引擎。
其实我们一直也在偷偷的在去做一些新的模块,争取能够帮助到我们的社群,跟大家汇报一下,现在我们正在做的事情,第一个的话呢就是我们把我们的这个r chi,也就是我们面向graphics底层的东西。
我们又把它这个就是又更新了一个一个,重新的结构,因为以前我们RH还写的不够专业,我们这次的话呢,争取给他换的稍微专业那么一点点的RH,这样的话能够未来大家想要移动端移植啊。
大家想往这个其他的甚至游戏主机移植的话,提供这样一个一个帮助,另外一个的话呢就是说呃,包括特别是对于DX12啊,对于这个metal特别是metal的支持要变得更好一点,另外一个的话呢。
就是哎这个是我觉得非常的这个,非常的amazing的一件事情,就是我们前两天我们有个同学这个发奇想,我们给我们的PICO还写了一个GPU particle,也就是说虽然你看了这个图上,你看不清楚。
现在我还配视频来不及了,然后呢,但是的话我们是真的实现了一个非常简单的GPU,PARC系统,这样的话诶大家可以在皮克罗里面可以去看看,这个GPU particle该怎么去实现。
当然那个我们做的是非常简单的,给大家做了个框架,那么有同学们,如果想要PICO做个自己的小游戏啊,比如说做一个你自己的毕设的话,我相信你可以秒杀那些没有用过PICO的小伙伴。
因为我们104的精神就是人均一个,这个就是开源引擎嘛,然后另外一个的话呢,就是说呃我们现在的话呢,就是在这个就是我们的皮克罗引擎里面,还加了一个小小的debug做系统,为什么加了个debug做系统呢。
因为现在好多同学们跟我们讲说,他们想要PICO做自己各种各样的小应用啊,想要做自己的小游戏,那实际上的话呢,如果你真的作为一个稍微复杂点的开发的话呢,你就一定要有这个debug做系统。
而且这个系统呢写不好,可能会把性能写得非常低,所以的话呢我们就加入了这样的一个,第八个做系统,然后争取再给我们一两周的时间,因为我们这是开源的代码,所以我们不好意思把代码写得特别的丑。
所以呢我们会做一些code review,如果我们觉得质量可以的话,也给大家,所以说不定的话就是说我们的104课程啊,这个告一段落之后的话,在新的课程还没开始之前。
我们可能会持续性的去对皮克洛进行更新呃,到时候零四课程的可能,games的视频号我们不能用了,我们可能会到时候大家可以在B站上找到,我们自己的视频号,然后的话呢我们也会定期的给大家讲一下,皮克罗的一些。
比如说结构讲解呀,或者是皮克O的一些大家要的什么功能,我们怎么去开发,跟大家一起,能帮助大家就真的实现我们这个课程的口号,就人均一个自研引擎对吧,那么另外一个的话呢就是上一节课的话呢。
其实同学们在那个我们各个QQ,那个就是微信群里面讨论的真的是非常的热烈,我自己都没有想到,然后呢,这里面的话呢就是同学们也问我们的一些问题,这是我们从大家问题里面挑出来的。
第一有同学们问我们说诶有没有游戏,它混合了真同步,和这个就是说呃那个状态同步的啊,其实是有的啦,就是大部分的真正的游戏的话,很多时候都是这样,举个例子吧,比如说我们玩一个MOBA游戏,MOBA游戏呢。
真正的游戏的game play,就是你进入到一起游戏的时候,很多时候大家会用的是真同步,但是呢你进入到游戏大厅呀,比如说你看到一群人在那跑来跑去啊,那时候玩家特别多啊。
而且又对游戏的逻辑要求不是那么严格的话,其实状态同步就可以了,所以说其实很多的实战性游戏的时候,都会把两种状态给混合在一起,那还有同学问我们一个问题,就是说哎,如果将来以后整个游戏都变成了语音游戏了。
我们是不是就不用学这个网络同步,这些东西了啊,这个怎么说呢,这件事情首先还没有发生对吧,我们还没有看到真正的云游戏引擎,那么我也不敢说的特别的断言,但是呢我觉得肯定了,大家如果都上了云游戏之后。
那很多网络同步啊,包括今天这节课我们会再给大家讲的这个防反,做反作弊啊,会简单很多,但是呢我个人觉得就是说,如果是真的是超大规模的游戏的话,你还是需要大量的这个状态同步的。
因为我不可能把所有的用户的输入,直接连到我的server端,你前面还是有很多的类似于client的东西,它可能做的比较轻,所以呢,特别是如果用户从不同的地域接近来的话。
但是前端还是有些节点来进行这样的处理,所以我个人认为状态同步还是必要的,在整个这个游戏世界中的话,可能是同一个真同步,那说不定真的就像大家讲的,那个世界是一个真核状态,同时混合的一个状态。
但这个里面的话呢,我觉得现在还在一个呃,大家在做很前沿的探索阶段,所以说啊我是我相信再过几年会逐渐的清晰,然后最后一个同学也问我们一个问题,就是说诶就是说如果是不是真同步了,就没有人作弊了。
其实上节课我已经讲过了,就是原则上来讲,真同步确实能够防范很多的作弊,但是呢也不能够防范掉所有的作弊,举个例子,比如说上次也讲过,比如说我把地图全开了对吧,什么战争迷雾完全没有用了。
比如说我打撸啊撸对吧,对方出什么英雄对吧,对方在干什么事情,我一清二楚,其实如果是真同步的话,我确实可以做这样一件事情,为什么呢,因为他所有的状态全部同步到这,我们是一模一样的那个逻辑。
如果没有做必要的防范的话,我可能连他在商店里出了什么装备,我都知道很清楚对吧,所以说啊这这个东西的话呢,也就也就是说很多事情,他都是就这也是做网网游的,非常复杂的一件事情,就是说因为你架不住。
就是大家会从各个角度去尝试攻击这个系统,好的好,那就是我们这一次整个社群的一个反馈,在开始今天这节课之前的话呢,我给大家做个简单的预告,首先的话这一节课讲完,我们网络课讲完之后呢,我们会暂停一周。
然后后面会开始我们的高级课程,那为什么我们要暂停一周呢,因为我们的高级课程,每一节课实际上都是非常非常重的一节课啊,其实我自己压力很大,因为我们选了三个topic的话,应该来讲都是分量很重的。
而且技术密度非常高,我还不是特别有信心诶,我第一个,我自己能不能把这个知识掌握得足够的准确,足够的到位,第二个就是说能不能在课件上给大家讲清楚,比如说我们的第一节课的话,我会给大家讲真正的面向数据编程。
就d o p dorange programming和job system,这个是对于现代高性能引引擎,或者是系统开发来讲的话,是一个非常核心的一个架构对吧,那这样的话如果这套体系的话。
其实这就像现在很多商业引擎都没有完全做到,比如说我们那个unity著名的ECS对吧,也是在尝试往这个方向去发展,那荣耀其实它的新的那个massive的这个系统,也在做这样的一件事情。
这是我们的第一个advance topic,那么第二个advance topic呢,那就是大名鼎鼎的对吧,就是虚幻五的那个NORMAN和拿来night这两个技术,那这两个技术呢。
说实话复杂度还是非常非常高的,就是说你了解他的大概可能呢没有那么难,但是你真的去一个一个知识点去理解它,然后能够把他这些东西串到一起的话,其实非常的复杂,真的是要对这些高手还是要保持敬畏之心。
就是说这两个技术的话,就是说从他技术概念很早以前就有人提出来,但是还还是很了不起的一件事情,就是大家真的在工业化上面,把这个问题解决掉了,所以啊我也是诚惶诚恐,我说一节课的时间我能不能把它讲清楚。
那么第二个的话呢,就是大家诶喜闻乐见的motion matching对吧,这个这个还有什么呢,APPGC就是那个基于pro procedure,generate content对吧。
这个也是大家特别喜欢的一个一个内容,但是这里面PGC的话,你的内容其实也是非常的多,而且很多孩子不是不是我特别熟悉的领域,比如说胡迪尼,我用的就不是特别好对吧,那那那这里面的话就有很多东西我们要去准备。
所以呢我们也会跟games课程组商量,能不能就是说每节课都能中间空一周,这样的话我们课程组能够进行更充分的准备,当然大家也可以在社区里投票,说我不需要,我就是要三节课连着讲,那我也没办法了。
我觉得勉为其难对吧,如果那个games允许我们这样调整,如果大家也支持我们的话,我个人会倾向于就是说每节课花两周时间准备,这样的话能讲得更透一点,因为这几节课都是啊非常的硬,这个里面我要做一个高能预警。
前方高能,所以的话呢这是我们在下一个就是整个基础,今天是我们的基础课程的最后一章嘛,然后这三节课呢是我们的高级课程的开始,就未来的话我们有可能会跟games商量,就是啊,这个会可能可能考虑给大家开一个。
二零系列的高级课,对不对,但是的话呢我们先拿着三节课给大家做个预热,看看大家喜不喜欢这些东西,那么那如果真的要开高级课的话,请大家允许我们先躺一年啊,躺个半年,我要我要好好的回点血了。
OK那所以这个地方呢也给大家做一起讲一下,我们后面的课程安排好的,言归正传,每次开场10分钟回到我们今天的课程,就是继续讲我们的online gaming architecture。
那今天讲的呢就是高级的topic,我记得我上节课卖过一个关子对吧,我说虽然我们上节课讲了那么多,还是蛮硬核的东西,连网络技术协议都跟大家讲一下,大家意识到说原来我要做一个online gaming。
连网络协议我得自己都得改一改对吧,都得写一写,确实还是还是这个蛮硬的,但当你把这些硬菜全部学完,我也懂了,什么叫真同步,什么叫状态同步,我们是不是就能做一个online gaming呢。
在上节课我最后一页,我说唉,大家可能不要高兴的太早,这些都只是foundation当你真正的做个游戏的时候,实际上还有一些很有趣的东西我们没有掌握,那这时候你的游戏做出来,你说能不能联网呢,能够联网。
但是你打起来就是很奇怪,所以今天这节课的话呢,是真正的教大家怎么去做网游对吧,那么这个东西的话呢,用一句更简单的话解释,就是说,假设你们你们俩好几个同学们一起做个游戏,分一个团队。
如果有同学自告奋勇的把那个online game的basic,那个那个课程里的东西全部实现完之后,你呢就可以很愉快的做那个高级的部分,确实你可以装作它下面的东西都不知道,没关系,那你接下来在上面的话。
你来看看你要解决什么问题,OK好,那么今天呢这节课的话呢,我们的structure首先还是从game play上面的要求讲,我们会跟大家讲,就说如何在不同的客户端之间怎么同步,玩家的移动。
Character moon replication,那大家想想哇,连网络移动同步这件事情,都要单独作为一个章节来讲对吧,这个听上去好像有点意思了。
那么第二个的话呢就是A叫head registrator,简单翻译就是如何在网络游戏的情况下,我能打中敌人,而且能正确的打中敌人,你想想看做一个游戏,你就又不能移动同步,又不能打中敌人。
那你这个游戏肯定是不成立的,所以我上节课为什么说,学完上节课还不足以做游戏,就是这个道理,因为这两他是大家首先要掌握的,有了这两盘之后呢,大家基本上就知道怎么就做游戏了,然后接下来第三章节呢。
我给大家讲一个诶,我们一个M游戏,就是说很多玩家在一起的这样一个游戏,它不一定是一个MRPG啊,可能是个MOFPS,Whatever,它的网络基础架构大概是怎么架的。
它这个其实不是network architecture,实际上是他整个这个啊server端的这个framework,应该怎么去架,但是我们因为时间有限,我们只会跟大家讲这个纲要,让大家知道这个框架。
然后呢最后给大家讲一下,诶,这个里面,其实如果你要做这样的一个游戏产品的时候,你最关注的一个东西是什么,诶你也得优化它的带宽,如果带宽不优化,你会发现你的服务器内部都会炸掉。
还有呢最后一个也是大家特别关心的,有感感兴趣这个话题就是如何反作弊对吧,那么反作弊的反面是什么,叫作弊,那作弊这件事情呢,我要跟大家高能预警一下,就是说,根据我们国家这个这个信息安全法的规定啊。
大家这个非法入侵计算机系统是个违法行为,那大家同学们一定不要试啊,虽然你们知道这些技术,但请你们不要试这个试了之后真的不好,那么最后一个的话呢,我们会荡开一笔跟同学们讲一下,就是说诶。
如果我们要做一个非常时下最热热烈的,最火爆的开放大世界对吧,那我们要做开放世界,你最基础的一个架构该怎么去架它呢,当然我们还只是点到为止,但是我觉得也能够帮助同学们去理解和思考,一些有意思的问题。
所以这就是我们今天往那个online game,architecture的这样的一个高级篇,跟大家讲的内容怎么样,大家觉得这个课程提纲还是让诸位客官满意吧,好,那接下来的话呢。
就是我们开始我们今天课程的正文,首先第一趴的话呢,我们给大家讲一下,就是说角色位移的同步,Replication,replication的意思就是诶我在那边复制出来,这个词,听上去很简单对吧。
那为什么这个问题要单独拎出来讲呢,其实啊就是说大家知道在上节课里面,我们讲了这个网络的传输不仅不稳定,还有什么,还有还有lagging,他是老师会有一个latency对吧。
我们上节课专门分析了各种的就是延迟,那实际上的话呢,就是我在我的玩一个游戏的时候,我看到别的小伙伴在那个世界里跑来跑去,真实的情况是什么呢,是那个小伙伴自己已经跑到很前面去了。
然后呢他需要把自己的状态诶,他首先自己有个tick,它不是随时随地发大家发给自己的服务器,这中间的话从他到服务器是不是有个延迟,所以服务器你看这就是如果那个上面的小伙伴,自己是个蓝色的。
那么它同步到中间那个灰色的话呢,就是这个这个服务器服务器比较慢,半拍好服务器,老人家他自身的tick还比我慢的吧,一般服务器我们不讲师个十帧每秒嘛,对不对,好他那个老人家反应过来了。
然后再把这个这个状态replicate到我这边,无论你是真同步还是状态同步啊,那我们这边假设你做的是状态同步诶,到我这边,就是我下面最下面那个红色的那个区域的话,是不是变得更慢,而且你看我的那个移动。
是不是一个消息来了之后,诶,我傻了,我就走一步,一个消息来我就傻了,走一步,那么当然了,我们说如果延迟特别小对吧,比如说你每个1/10秒或者是1/20秒,有一个,那我看到别人在我的客户端上同步的时候。
诶,看看看看看看还行,但是如果大家想象一下,网络讲师LEX就是网络的latency不稳定的时候,我是不是会出现那个人就是一抖一抖一抖一抖,一抖一抖,对不对,所以说我要实现一个最简单的一个。
对方移动的同步,那么好像用一个最简单的消息来了,我去更新这件事情好像是不对的,因为整个这个状态看上去就非常的奇怪,所以在这样的一个情况下的话,我们怎么去解决这个同步问题呢,哎这里面我们就祭出我们的。
大名鼎鼎的数学工具了,叫什么呢,叫差值对,差值这个东西的话呢,同学们如果在学大学高数的时候对吧,学工程数学的时候应该是耳熟能详了对吧,这个凡事不举就是差值嘛,对不对,只要觉得这个信号不smooth。
我们就开始把它smooth一下,怎么smooth,我就跟你差值嘛,那么差值呢有两大流派对吧,第一个流派呢我们叫做INTERLATION内差对对,还有什么呢,extra polation y差值对吧。
内插值我们都很熟了,对不对,我们有多个控制点对吧,我们去内差值,大家还记得我们在前面很多会反复提到的,比如说cut more曲线啊,那个BASI样条,BER样条好像比较复杂,它不会控制点。
那cut more曲线它就很棒,它可以过所有的控制点对吧,而且让你线条看着非常的光滑,那么或者是我直接就是这个用一段段的折线,我也能插值啊,对不对,内差值大家想到了很正常,对不对。
但是呢诶在网络同步的时候,我们可能还需要外插值,外插值本质是什么,是预测对吧,比如说根据这个哎我们这个今年的人口出生率,明年的出生率,后年出生率我们可以引引引出一条曲线出来,那是什么,那叫外差值对吧。
那么其实在网络这个这个角色位置同步的时候,实际上,这两种差值还扮演了一个很不一样的角色,所以呢这个section我给大家讲一下,就怎么利用差值来让这个这个replicate。
这个character动起来看上去更smooth好,那我们先讲这个内插,内插其实非常简单,就是说当我的网络随着时间不停的给我,信息包的时候,这个包可以不均匀啊,他可能一开始密一点,后面因为网络有波动了。
我会稀疏一点,没关系对吧,我可以根据你的时间,我把你这些只是给你插出来,而且我可以保证你的平滑性,保证平滑,大家在前面的课程也学过了,其实都比较简单对吧,比如说用cut more曲线。
就可以很容易地用一个POLLAMO的计算复杂度,我就可以叉出它的一条光滑的过渡曲线好,那这样的一个方法的话呢,其实在我们在做网络同步的时候,就可以很简单的用下来了。
那这里面有一个小小的trick是什么呢,就是说我们以这张图为例啊,就是在这个我们的就是client,在那个就是server端,它如果同步过来别人的一个位置信息,注意啊。
这里面我把那个就是那个那个authorize,那个那个client,我把它隐藏掉了,我最上面就直接server了,已经知道那个撞这个角色在S1S二两个状态,就沿着时间轴。
那么它同步给我的client的时候呢,实际上已经有一个小小的延迟了,对不对,好,这个时候我要插值,我知道我是在S1S2之间,但是如果我每一次都要去这个急急忙忙的,立刻马上去插值的话,你会出现什么情况。
就是你查到了之后,后面的数据还没有来,因为你要跟未来去插值,对不对,除非你做预测,所以呢你要用内插值的时候,有一个很重要的一个trick,就是说我要把从server端来的这个角色的状态。
要把它cash到一个buffer里面去,我要稍微加上一点点的offset,然后呢,这样的话,当我在比如说S1和S2之间差值的时候,我有足够的时间等那个S3到我这边来。
所以这个time offset其实是非常的重要,而这也是就是内插值的这个游戏引擎,它的一个很典型的一个特征,就是说如果server到client的这个延迟已经是,比如说50ms了,我很可能会要让我本地。
我在master,比如说一帧的时间在八分个100ms对吧,我可能又增加了额外的延迟,但是的话呢它的好处是什么呢,就会让我在客户端上看到对方的移动,无比的平滑,这就是内插值的一个很重要的一个特点。
就是说它的延迟是会被加剧的,那如果是这样的话,诶我们用这种简单的方法,你会发现当上面的人在动的时候,server慢了,但是到我这边看上去的时候,大家发现没有,其实基本是平滑的。
其实这里面是有一个潜在的bug,就是说啊如果那个真正的就是那个authorize那个client,就是那个那个主动在跑的那个对方,他跑跑停停跑跑停,如果说跑停的频率很高的话,其实你用内插值的方法的话。
有可能会把这个这个这个这个状态,都可以smooth掉对吧,这就是差值带来的一个额外的你,你不能说它是好处还是坏处,反正它让信号更加的平滑,但是呢我们的人眼很有意思。
就是人眼观察这个世界的所有信息的时候呢,我们都会倾向于去看那个就是连续的信号,所以呢这也是就是内插它的道理所在,就是我们一般来讲一辆车也好,一个对面来了一个一个一个一个玩家也好,它的移动如果是光滑的。
就相对就是不会急停,急走的话,我们会觉得它移动得更加自然,其实也并不care那个玩家到底是真是怎么弄的,所以这就是内插,但是那一插呢实际上它有一个问题,就刚才我讲的就是诶他加剧我的延迟对吧。
而且实际上在两个客户端的话,我们看他的状态一定是严格不一样,对不对,因为我看你的世界慢了,比如说150ms或者200ms,你看我的世界也是200ms,这个200ms你觉得多吗,它也不多。
但是呢对于这种高速移动的游戏,举个例子,你玩的是一个赛车游戏对吧,那么这里面举个例子,比如说在这个就是最啊,应该是最,不好意思,我左右不分,我小时候左撇子,然后比如说这是我的左边对,左边的话。
大家看左边那个红车,他自己呢是authorized的对吧,他觉得我应该要撞到那个灰色的车,因为灰色的车是同步过来,但灰色车呢他自己是往上跑的,在在在灰色车的客户端,他看到的。
首先红车的位置是不是诶稍微滞后一点,所以红车其实没有到我们的交汇点,但是灰车自己觉得自己呢唉我已经跑掉了,因为我的速度总是领先于server嘛,那这样的话就会出现一个很有意思的事情,就是说啊。
红车的authorized端认为我已经撞到了灰车,但灰车的authorize端的话呢,他会认为我自己没有撞到那个地方,就是个罗生门了,到底是你们谁说的是对的呢。
那这个其实呢就是有interpolation,就是内插值必然会带来的一个,很头疼的一个问题对吧,那么这个问题的话呢,再就是说碰撞没有那么敏感的,比如说我自己个人移动的游戏呢还可以,但是对于你如果开船。
比如说我们要做一个像战舰世界的游戏对吧,我们要做一个online的,像GTA这样的游戏,我们互相拿着车开碰碰车玩,那这个问题就变得很很头疼了对吧,所以呢诶这个时候呢,我们就要祭出。
我们另外一个可能的法宝是什么呢,叫做extrapolation,外差值什么意思,就是说我既然每个客户端都知道,我得到的消息肯定是比真实的世界晚,那假设我对这个我的latency是有一个估计的话。
我是不是可以根据你现在告诉我,你的位置和速度,包括还有加速度对吧,我可以预测,其实如果这个中间比如说这150ms里面,没有任何其他的事情发生的话,你就应该出现,就是就是怎么说呢,这有点相对来讲的。
就是说我们的时钟是不对齐的,但是的话我知道此时此刻哎,这跟相关的没有关系啊,我这个混淆了,这其实是牛顿的时空观,是绝对时空无关,不是相对使用感,这个里面不能够做民科,就是在这个绝对时空里面,你此时此地。
你在地球的另一端,你实际上是在哪个位置,所以说这个其实呢就是外查的核心原理,就是如果我就像我说的啊,我相信以前我看过一个一个动画片,我还是个这个古装剧,就是啊有一个人收到一封信,他这封信他说诶。
说什么什么人要要要要要谋反了,然后呢他收到信之后,他马上就派兵就出去了,然后旁边人问他,你为什么派兵出去,他说这封信技术啊到这边至少要一个月,所以那个人早就已经模仿,好像把那个什么什么已经杀了。
所以我这时候应该不用等了,直接去清,就直接去抓它就可以了,其实这就是外差的思想,就是说因为我考虑了信息在路径传递中的,这个latent这个这个时间耽误,所以我预判了别人的行动对吧,怎么样。
这个预判了别人的预判,对不对,所以呢我这个时候就会去这个派兵过去了,这个就把这事做了,其实外差的核心思想就是我已经预判到说,你现在其实应该是什么呢,虽然我没有收到你的信息包。
这个地方稍微有那么一点点抽象,但这个东西大家一定要理解清楚,为什么呢,这个在后面讲,那个比如说怎么样保证彼此能打通对方,这件事情,想要这种外差的思想就预判了别人的行为,也是非常重要的。
好那这个地方的话呢,我们就遇引入一个大名鼎鼎的算法了,叫dead recording,对吧,这个中文翻译我也不知道叫什么算法,这个DEBUCI这个名字听上叫死亡什么什么,这个也挺奇怪的。
但是呢他这个算法其实非常大名鼎鼎啊,他以前是航空航海上面的一个概念,什么意思,就是大家想要啊,我一架飞机在空中飞,以前没有GPS的时代的话,我大概知道我七发出发点的位置,然后呢我只有一根空速管。
这空速管告诉我相对空气的这个这个相对速度,然后呢我又知道说诶大气风的方向和速度,然后呢我要想去我的目标点,我是不是要规划一条一条路径,去对抗风对我的影响,而且这个风格一直在变啊。
最终能保证我能到达我的目目标点,其实这个在航空和航海上还是非常勇的,海上有什么东西,有洋流,对不对,想想在那个浪漫的大航海时代,大家没有GPS的时候,我怎么去导航,能够精准地到达一个海岛。
这件事情其实还是很很很厉害的一件事情,所以这个算法的,就是在我们这里面用的一个核心是什么呢,就是说如果我们收到了一个网络包,我们知道我现在已经跟这个,你的真实状态已经不一样了,时候我怎么去追你。
有两种追法,一种追法是说,因为我知道我现在的位置姿态跟你不一样,我直接朝朝着你这个姿态去追,对不对,那这地方会出什么问题诶,我追到你的时候,你其实已经到另外一个姿态了对吧。
所以这个时候呢我必须要预判你的动作,对不对,所以DCI的这个在我们这里的算算法的思想,就是说我怎么去预判别人下一步的动作,那这里面的话讲一个大名鼎鼎的算法叫PROJECTIVE。
velocity blending对吧,PVB它的核心的思想是什么呢,就是说当我诶这个地方稍微有一点点小高能,大家如果看不懂没有关系,因为但是换气算法是个很经典的算法。
而且大家如果要写到这样的同步的时候,有很多的资料可以去查,我这里面就跟大家讲一个最核心的一个思想,就是说当我现在发现我的位置,就是经过了一段时间之后,诶,我发现我在点PP0对吧,我的速度是V0。
然后呢我再往前走,这个时候呢我突然收到了一个包,这个包告诉我说,哎哥们儿,你错了,其实呢你真实的位置应该在这个P01撇点,对吧,你的速度呢应该也在V01撇,你这时候还收到了一个A01撇的加速度。
那大家想想看诶,那我是不是经过了一个就是一个固定时间之后,我们假设这个时间叫tb啊,这个b stands for what呢,就是代表的是blending对吧,就是经过了某一个时间之后。
我的心的位置是不是在PT1撇,等于你当前的就是我收到你这个包,告诉我当前的精准位置对吧,加上当前的真实的速度,和当时真实速度的加速度的这个时间平方对吧,这这个公式应该是非常简单,我当时第一次看。
我记得我当时我第一次看到公式的时候,我说这是什么公式,后来一想,这不就是牛顿第一第二定理嘛,对不对,就是速度加速度的变化嘛对吧,很简单,就是诶我就知道啊,其实经过了一个固定。
比如说一个从现在的T0到TB那个时间之后,你实际上应该出现在那个PT撇那个点,那我不幸的是说在我的客户端里面,诶你的位置还在P0这个点,你的速度还是V0对吧,那我接下来要做的事情是什么呢。
我不就是找一条曲线,让我能够着你吗对吧,仔细想想,这个算法是不是很简单好,那具体怎么去构它呢,其实dead recounting这个这个PVB的这个算法,其实可以这么说,非常的简单粗暴。
他说OK我假设我提个要求,就是在这个一个时间固定的时间间隔里面,比如说我希望在tb的时候,你就B就指的是blending,就是大B的时候我就要追上你,那实际上呢我就在这个时间轴里面,我做两个差值。
第一个差值是什么呢,我对我的速度进行差值,那我就希望我的速度,因为这里面我会假设我的速度,5月嘛我就打,我就希望等到了那个就是说到tb的时候,我的速度跟你一样,那其实就是个线性差值对吧,第二件事情呢。
诶我要对我的位置进行价值,这里面就有一个有趣的trick了,就是说因为啊当我没有收到你的新包的时候,其实呢这个这个这个particle,它自身也会受到一个速度或者加速度的影响,对吧。
它会如果没有收到那个新包,它是不是沿着上面那个红色的线去走,对不对,他会这样走下去,但是呢因为我收到了你的包,所以我就知道说你在那个tb那个时间的话呢,你会沿着那个绿色的线。
走到那个新的PT1撇的那个点,这里面,注意这里的一撇就是假设是真实的位置,而没有加一撇,就表示是我这边复制你的位置,那我其实最核心的方法是什么呢,就是我在这个就是T0到TB之间的时候。
我线性的在两个位置之间依次的进行差值,一开始的时候用我的聘礼,到后面逐渐逐渐逐渐逐渐逐渐逐渐,我越来用你条绿色线的那个数值,其实看上去数学很高深,但实际上就是一个非常简单的线性差值。
但是这样一个差值的好处是什么呢,就是说我们不会看到这个物体的位置,瞬间的被变掉,他是逐步逐步的诶追上了那个目标点的位置,而且呢大家注意这里面有个细节,就是说这个PPPPB的算法的话呢。
它并不符合动力学原理,它其实就是对位置进行一个非常生硬的差值,所以的话理论上讲的话呢,他有可能出现一些,就是它的速度和加速度一直在变对吧,但这不重要,重要的是说我最重要的是,到最后我的到了那个时时间的。
tb的那个目标点的时候,哎我的位置也给你重合了,我的这个就是速度也跟你重合了,对吧,加速度我就换成你的了,那我们俩就一致了嘛,对不对,那么这个时候如果来了个新包的话,那我们的结果。
如果你在这过程中没有发生新的变化的话,我们的结果其实是一致的,这就是这个带康尼的一个核心思想,但这个方法呢其实他的挑战是什么,等你在tb的时间追到之后,诶新的包来了。
你发现在这过程中间哎又发生了一些新的变化,其实它的位置又发生变化了对吧,所以说你仔细看看这个它的实现,就是你会看到一条啊蓝色的曲线,就是你真实的运动轨迹,你一直在尝试追那条绿色的线。
而绿色的线呢是真实的,就是author在的玩家的这个在世界上的移动,而你在这个RPC端移动的话,总是尽可能smooth的,就是尽可能平滑的,但是呢一直在努力的追求着那个哈。
就是那个真实世界的那个就是AUTHORIZON的移动,其实我们以前在做一些网,网络同步的debug的时候,观察这两条曲线的这个走动的时候,是特别有意思的,有的时候你怎么记bug,它。
我会在authors端反向的把那个就是rap,RAPC端的这个数据传回来,然后两边进行比较,看两条曲线的这种重合度,大概多久能追得上,包括我们会加上一些固定的一些网络延迟,我们会看这个延迟的情况下。
这个会不会让DCI算法会出问题,所以大家如果有兴趣写这一趴的话,这里面还有很多很有趣的小trick,让你这个效果更好,我今天这里面给大家介绍的还是最简单的算法,那么这个这个算法的话呢。
其实大家理解了这个最核心的思想就可以了,其实到后面的话会有很多小的变种,帮你去解决各种各样的小边界情况好,这其实就是那个外插值的一个一个想法,那么其实对于赛车这样的游戏的话。
外插值是一个非常必要的一个东西,但是外插值呢其实也会有问题,比如说当我们发现对这个世界进行碰撞的时候,对吧,比如两辆车要撞起来的时候,你也在外差值,我也在外插值,那我们有可能就是说。
虽然我们其实已经撞到一起了,但是呢因为你的位置是外插值过来的,你会发现它就不管不顾的插进了我的车头里面,对吧,你会发现诶这两个的行为就很奇怪,而且呢因为就是大家知道,我记得我在那个就是物理那节课讲过。
就是说我们在做这个刚体动力学的时候,会发现那个server会有一个有一次的问题,就是说当你发现两个缸体,事实上已经发生穿插的时候,很多物理引擎会给他们一个很大的力,会把那个物体猛地推开来。
所以本来你觉得是一个不是特别重的,一个一个一个碰撞,但结果你发现整个东西被弹飞了,大家想象一下,你们在玩一些带那么一丢丢,物理模拟的网游的时候,有没有经常会发现这样的bug。
就是A看似两个两个东西只是轻轻地撞在一起,但是你会发现它非常恐怖的弹开来了,如果发现发生这种情况的话,那就是有可能就是A那个对方的游戏,可能用了外差值的一些算法,然后呢。
物理的两个那个就是那个他们两个actor,真的穿插了,穿插了之后,物理引擎的话会反向的给一个很大的利普,他们推开了,这个有很多时候可能就是这个原因,那么对于这种情况怎么去处理呢。
其实这个问题首先我要跟大家讲一下,非常复杂,挺难的,真的很难啊,这基本上你会针对不同的游戏,比如说你做个赛车游戏,你做个飞机游戏对吧,你作为一个boating的游戏,那你都要单独考虑和设计过。
那这里面有一个非常简单的一个思想,就是说我会在客户端提前的进行物理的检测,也就是说,其实如果我在我的客户端已经检测到了,我已经和某一个,比如说啊,强或者是另外一个物体发生碰撞的时候。
我就会把这个就是位置同步的权利,从网络同步,和他的那个,比如说DCI的这个这个这个外差值的这些算法,切换回什么呢,切换为物理引擎的算法,这里面是有一个switching的。
但是呢他可能是一瞬间切给物理了,然后呢过了一段时间之后,我再逐渐的把这个过程回还给你,比如说像那个就是这里面我们举的例子,就是说啊watch dog,看门狗里面它的假定是说撞车之后,如果我没记错。
好像是一秒钟之后,我们逐步的把这个就是这个位置控制权,交还给这个来自于网络端的消息,这样确保我们的世界状态是同步的,那一秒里面其实很多事情我就不能动了对吧。
那完全交给我本地就是client端的物理来结算,那这里面其实会导致一个问题,就是说我们不同客户端的,这个物理模拟的结果是不一样的,我还记得大家还记得。
我在上一节课讲到物理的deterministic的时候,讲过一件事情,就是说诶你输入条件有那么一丢丢的变化,比如说一辆车被撞飞的时候,可能有一个是这样,这样这样飞掉了另外一个世界。
你模拟手这个车是这样这样飞掉了,他俩的位置不会相差的非常大对吧,这里面又很麻烦,所以其实呢在很多的引擎里面,如果我们真的要处理这件事情的话,是挺复杂的,比如说有的算法是说诶,我预测到你可能要撞了对吧。
那我首先就把你这个那个,好像是那个那段时间的玩家在控制,我都给你关掉,当然这没有个假设,就是说人类的反应时间不会快过100ms对吧,就算电竞选手,好像也很难超过100ms的反应速度。
所以我如果在前50ms,我已经判断你要这个撞车的时候,诶,我全部交给双方的差值,而且位置同步起来,这样大家的结果尽可能的是一致吧,所以这里面是有很多很难的一些trick在里面。
但是这里面跟大家讲的这个事情,就是说,当我们真的用外差值去做这样的一个,一个一个应用的时候的话呢,哎大家一定要考虑各种各样的边界情况,这就是做网游的困难,就是网游大家记住啊。
就是如果你做个单机游戏做的很漂亮,很多很复杂的这种哎呀这个物理效果啊,你觉得很厉害啊,但是如果把这件事情做到一个online game里面,而且这个东西还能够就真正的跟game play。
结合在一起的话,其实这是一个在设计上非常挑战的一个问题,好这就是外差值,其实外差值的话呢也是一个非常重要的系统,所以其实啊这两种差值,对于我们一开始抛出的问题,就是如何在网游里面去同步玩家的位移。
是一个基础性的算法,那么这两个应用的场景呢也是不一样的,比如说内差呢一般会应用在,就是说玩家会经常进行各种各样的瞬间的移动,或者说突然很大的加速度,我想问大家一个问题。
你们觉得什么情况下玩家的加速度会比较大,大家会会不会觉得诶我开一个跑车游戏,加速度很大对吧,但其实这是一个错觉,实际上的话,如果我现在是个赛车游戏的话,即使你开的最好的跑车,它的加速度啊。
实际上也就那么回事,顶多一秒,比如说这个这个百公里三秒,百公里百公里两秒对吧,也就那么回事了,但是的话呢其实在这个游戏里面,真正加速度最大的是什么呢,是我们讲的controller,什么东西。
就是玩家自己,因为我们很多时候,大家在操控游戏里的角色的时候,我们要求角色很灵活,很有响应感,实际上在那里面角色的运动是反物理的,我们的加速和减速几乎是瞬时的,哎这个跟大家感觉不一样的呀。
大家会觉得我们不是有个提速的过程,其实不是的,如果我们真实的按人类的提速过程,去做到游戏里面的话,你会觉得那个角色很粘滞,就是你会觉得操作手感不好,所以其实包括我们的角色。
很多时候有那种什么哎瞬间位移啦,突然一下跳高了,其实在游戏里面角色跳起来或者是落地,他很多时候它的加速都是反物理的,因为如果真是按物理的gravity那个系数的话,你会觉得很怪。
所以说所以在很多FPS游戏里面,在MOBA游戏里面,我们一般用interpolation内差值比较多,因为内插值的好处是什么呢,相对比较稳定,它不会外,也因为外差时它其实是个危险的嘛。
你要去predict未来,所以有的时候会进入到一些我们不希望的状态,比如说外插值,有时候会把你插到墙里面去了,或者插到一个死胡同里面去了,就很麻烦,就是有些游戏写的不好,就会出现什么情况,我们用了外插。
结果呢,那个角色自己,OSA团觉得自己可以在世界里走来走去,但是在ROPA段的话,那个家伙已经钻到了墙的那头,过会儿又被拉回来了,你看起来也很奇怪,但是这里面解决方法也是有的。
比如说我可以本地还会做个物理检测,保证它不会穿墙对吧,那么另外那么如果外查呢,一般适用于什么样的游戏呢,就是诶这个它这个整个运动啊,是符合物理学规律的,比如说我们做一个像开船的游戏,开车的游戏对吧。
你看着它很复杂,但是呢这个船的加速也好,车的加速也好,包括给了给低音加速下,你调它ROTTO就是它的这个这个油门的话,它实际上整个的位置速度变化,都是符合物理学规律的。
这样的话我对他的未来的prediction其实是准的,所以这个时候的话呢,唉我们基本上是能够用外插的方法,去对它进行插值对吧,这个其实是有道理的,就是说我举个例子吧。
就比如比如说我们要做一个自动瞄准的一个,远程武器,让我去打辆车的话,这个车一般不会疯狂的,一会儿加速,一会减速,其实很难,所以我其实很容易做一些提前量计算,把它打中,但是我要打一个人的话。
这个人一块儿翻滚,一会左摇右摆,其实你做体向量的计算的时候,很多时候很难打中,他也是这个道理,那么实际上在真实的游戏里面的话呢,就是说呃,我们有的时候也会把两种算法合到一起。
比如说我们做一个像战地这样的游戏对吧,那我们可以对角色移动的时候,我们用的是内插,这样的话确保它的安全性,但是呢当角色上了载具之后,载具,因为它符合我们的物理学原理啊,那我们载具可以用外插的方法。
所以说真实的在游戏的场景中的话呢,这两件事事情是会混合在一起用的,也是一个,这就跟我们上次讲了一个什么,真同步和状态同步一样的对吧,所以大家千万不要就是我还是讲这句话,就是大家在学游戏引擎的时候。
千万不要陷入到这种甜豆浆咸豆浆之争,只要是一个方法,它产生了,它一定有它的这个应用场景,而且呢在真实的游戏世界里面的话呢,就是我们认为基本上每一件事,每一个方法都有它的应用场景的。
而且很多时候拿来主义能解决问题就是好方法,OK好,所以讲到这一趴的话,同学们大概知道了,哎,我们的这个角色,终于知道怎么在网游里面彼此同步了,否则你如果没有不知道这套算法的话呢。
那个角色看上去就很很诡异,好那我们知道这个东西的时候,接下来我们下一件要具体的问题是什么呢,我们怎么去打中别人叫hate registration对吧,这个词registration这个词是个专业说法。
就是我们怎么把这个击中的这个信息,互相能够对齐好,那为什么这件事情是很重要的,就是我们在打CSGO也好,打这个设计也好,我们觉得自己是枪神,那把我叫砰一枪,爆头特别爽。
但是在一个真实的online游戏里面,爆头这件事情其实比大家想象的还要复杂得多,首先当这个敌人出现的时候,他首先要经过一段时间同步到这个,经过一个RTT,半个RTT同步到哪,同步到服务器。
但服务器呢他很坏,他也不是马上处理,他还先buffer一下,对不对,在上节课讲过服务器的很多时候,它会Buff一起这个状态,然后呢在传递给你,好,服务器传给我的时候呢,哎我又要buffer1段。
那个这个又要经过一段时间,RTT到我这儿对吧,好到我这儿了,我又不是马上就看见,大家想到我们很多时候,本地也会buffer一下网络的状态啊,对不对,比如说你用的INTERLATION。
比如说是一个啊距内插值的这样状态同步的话,那我还做过INTERLATION,诶,这个时候我才能看到这个老哥,出现在我的画面里了,然后你这个时候再再经过,你自己的一个反应时间,说来我一枪爆头对吧。
大家想想看,你本来觉得是对方一瞬间出现在你的面前,然后你机智果敢的一枪把对方头打爆了,实际上在真实的物理世界里面,这中间已经发生了无数次的,时间的偏移和延迟了,那么在这么多的不确定性下的话。
我怎么知道我我真的能打中这个人的头呢,对吧,我说我打中了,别人怎么信我呢,所以这其实就是在这个网络游戏里面的,这个命中判定,实际上是一个非常难的一个问题,那这件事情难在哪里。
我第一个问题就是敌人到底在哪里对吧,还是搬出这张很经典的这张图,对不对,你发现就是说那个灰色的,就是那个半透明的,是别人现在真实的位置,也就是对方是那个玩家自己跑的位置。
然后呢中间那个半半透明的那个是什么呢,诶是这个我们的server端,server端呢稍微慢那么一点点,但是它勉强能追得上诶,然后呢再到传递到我这的时候,这个老哥是那个时我看到的是那个十的部分。
他已经相对于那个真实的玩家已经落后了,至少有两三个身位,现在看上去大概有4~5个身位以上的,这样的一个时间的距离,所以说这样的这么大的一个距离的话,我们到底怎么算命中他了对吧。
那么第二件事情就是说诶对方这样移来移去,我怎么就打中他了呢,而且对方的位置在同步的时候,很多时是不稳定的,然后还有一个更让人觉得难受的一个问题,就是说诶现在有一个掩体,一个cover对吧。
这个老哥我现在看见他的,他在那个掩体之外,我一枪命中他,但是他觉得我已经进了掩体对吧,他肯不愿意被你打死,那这件事情怎么去解决呢,所以说其实当你在网游里面,你看到对方一个人头的时候对吧。
尤其你的弹道不是瞬间的,你有的时候可能是有一个project,就是说诶我有个飞行的过程对吧,如果呢我还要加上一个重力加速度,我的弹道还有下坠,大家如果玩战地的话,就知道那个战地里的狙击枪。
它是有下垂的对吧,那好了呀,那这个时候我怎么样才能做一个完美的,这个是一枪开了完美的一枪能够命中敌人呢,其实这就是hit registration,也就是说射击命中判定的话,最核心要尝试解决的问题。
哎注意啊,这里面我讲了一个词叫尝试,什么意思,就是我事实上认为,虽然我这节课后面,我记得这下面会跟大家讲很多的方法,但是我个人认为,这个问题到目前为止,还是没有得到一个完美的解决。
因为确实是上帝老人家太完美了,我们就做不到,对吧好,那我们就讲这个问题,我们怎么去解他,所以这里面就引入了著名的这个这个这个这个,hit registration的概念,那么黑就是黑。
hit registration的话呢,在我的理解中呢,它其实啊,就是在一个online的一个非常不确定的网络环境下,我们让所有的client能够,关于我到底有没有命中我的目标达成一个共识,哎注意啊。
这里面讲的是共识,而不是这个fact或者reality,也就是说其实啊在一个网络延迟的环境下,你开了一枪到底有没有击中目标,这件事情并不存在,一个ground truth,就是一个真实的解,诶。
这个是个很让人绝望的一个结论啊,因为因为确实是因为在每一个人世界里面,你开枪的时间点,对方和环境所在的状态,对方所在的位置都是不一样的,你这时候开了一枪之后,那我们怎么说你一定能打中这个人呢。
特别像我们特别喜欢的那个爆头,对不对,所以呢在这种情况下,我们既然没有ground truth,所以大家最重要的是达成一个共识,说你到底算打中了还是没打中对吧。
所以这就是head registration的一个核心的目标对,那么his registration的话呢,实际上有两种大的解决方法的流派,第一种方法呢哎比较简单,就是我们的客户端来决定。
这个时候呢我们一般不叫his registration,我们叫head detect detection,或就是说诶我的射击检测就好了,而没有如果我们交给服务器端来处理的话。
我们一般叫它head registration,就是说诶这个我们的叫击中哇,这个registration怎么翻译的啊,不管了,反正就大家记住这个词就好了对吧,那么我们先讲一个呃。
最简单的就是说我们在客户端去判定它,其实客户端判定的游戏啊,一般来讲它有一些特征,比如说大家特别喜欢的这个PUBG对吧,这个有100多个玩家在一个世界里面,那么多的玩家,其实你说一枪打中,我。
让这100多个玩家跟我的服务器一起,达成一个共识啊,好像有那么一丢丢的比较难对吧,所以呢PUBG的话,我不知道他现在最新的版本,至少早期的版本它是用客户端去做的,哎这里面我后面会讲的就是。
为什么PUBG有那么多的挂对吧,大家听完这个section,大家知道为什么它有很多的挂了对吧,另外一个比如说这个世界非常的动态,非常的复杂,比如像战地,战地里面的话,有一有几座的时候。
你可以把墙整个拆了,我记得有一座我特别印象特别深,就是一个屋子,我可以一一块一块的把这屋子整个拆了,那时候我就觉得嗨的不得了对吧,然后呢我可以通过我拆掉屋子的那个墙的边缘,躲在那边给别人射击。
那这个世界如果是非常的动态,有大量的破坏的时候,其实呢我们会认为它更适合在客户端直接判断,那客户端判断呢它其实就非常的简单了,也就是说我就是一个head Scout,就是我去看一下我这个能不能打中。
那么注意,这里面就是那个对于这里面讲的设计游戏,specific了,就是说它有三种不同的弹道对吧,一种是说我开枪,我直接设一条速度无限快的一条射线,注意啊,这里的速度是无限快,你比光还快。
就是我开枪的一瞬间,只要你在我那条射线上,你就死了对吧,那这个的话呢就是说呃,很很多早期的设计游戏是这么设计的,那么一些比较,这个就相对追求这种真实感的游戏的话呢。
我们会追求说诶你的子弹还是要飞过去的对吧,最早比如说我做的halo,halo里面那个子弹很多时候飞的是直线,但是呢有些弹药它是打的是那个,它是有个飞行过程,所以你有的时候会展现一下我的秀操作。
就是看见子弹过来,我会尝试去躲一躲,其实大家如果打设计游戏就知道,如果对方的弹速比较慢的时候,特别是那种什么rocket launcher过来的时候,你觉得自己顺势来个翻滚测试,让过的时候。
你内心的那种那种肾上腺素分泌,会让你觉得特别的爽对吧,所以说这也是我们的乐趣之一,那么在一起更加拟真的游戏里面的话呢,就是他会加上一个这个抛物线对吧,这个其实是我个人还是蛮喜欢的。
我觉得这个就是因为我我我我,我觉得射箭是一件很爽的运动嘛对吧,那么其实说其实,因为因为我们的这个人类是狩猎出来的,所以说我们天然的对这种抛物线弹道,是有一种呃很很发自本能的一种愉悦感。
所以说其实在你在客户端的话,你用这三种不同的弹道都没有问题,为什么,因为你做的都是对的,那么其实客户端呢它的算法本身是非常的简单,就是说我只以你本地看到的东西为准,就是你一枪打过去。
然后我你你在你本地看到对方在什么位置,就是什么位置,你这样的好处是什么呢,它非常的准确,非常的符合人的直觉,所以我做那种很精准的爆头啊,做一些非常复杂的操作都是可以的。
所以说基本上在客户端判定的射击游戏,一般来讲都是你射击手感比较好的游戏,但不能说是最好,因为手感好,还有很多很复杂的原因的来来影响它好,那是不是你客户端说诶我打中了就一定打中了,这个呢,当然了。
我们可以这么干对吧,但是呢作为一款网游呢,有的时候我们还是不会那么容易的放弃治疗,所以在server端的话呢,我们会做一个过程叫做verification,我们会做一个验证。
这个验证其实一般来讲做的都不会特别的麻烦,因为我既然已经选择了相信客户端对吧,那我怎么办呢,那我很简单说诶,你客户端你把你开枪的位置告诉我一下对吧,然后呢你告诉我你到底打中了谁,你到底打中他哪一点。
你发给我,发给我之后呢,server就会说哎,首先我验证一下你开枪的点是不是假的对吧,比如说如果在服务器端,你的位置和你开箱的点差了10万8000里对吧,那我知道你在作弊,那我给你把它踢掉。
然后呢你说你打中了张三的哪个点诶,我说这个,如果我发现那个你的被击中的那个家伙,和你击中那个家伙的位置点差的也很大,那你可能也是在乱说对吧,那这个地方我也认为你可能在作弊,对不对。
你比如你本地可能修改了那个角色的位置,比如说你写个外挂,把所有的敌人都拉到你的面前,然后你一枪一枪把别人枪毙掉对吧,那这个我肯定能detect出来,最后一个的话呢,如果这两个都没有作弊好,我接下来看。
就是说从你的开箱点到这个你的hit point之间,就shoot point和hit point之间,哎我们连一条线看看中间有没有这个障碍物,因为你想想如果我做个CSGO这样的游戏的话。
你说OK我开了全图透视的这个外挂,然后呢我我确实是真的打了那个人,但是的话我根本不管所有的墙和掩体对吧,那这个这个我们的服务器端表示说唉,这种低级的问题你还是不能糊弄我的,那我还是能帮你检测到。
就是我做一个简单的recasting,就知道你有没有穿过墙体去打了别人对吧,但是CSGO里面有些墙是可以好像可以打穿的,Ok anyway,所以的话呢,这个其实是在这个就是客户端的这个。
这个这个就是hit detection的时候,我会做一个非常简单的这样的一个检验,但是真实的就是说就算是一个客户端的这个,检验的游戏里面的话,呃,我们实际上的真实的情况比这个要复杂很多。
我这边举个简单的例子啊,比如说大家看了大名鼎鼎的这是什么,这是守望先锋,对不对,守望先锋诶,他就是选择了在客户端做检测,所以手腕的设计手感确实是不错的对吧,那人家是怎么做的呢。
这里给大家看看这个这个很很神奇的一件事情,就是说你在客户端说你打中了一个人呢,实际上他在他的服务器上会做一个检测,说你到底有没有打动他,但是呢他也知道说哎呀,我们彼此之间的网络的情况非常的复杂,对不对。
很多不可信,他就以那个人为核心,做了一个box,这个box可能做的比他本人大很多啊,就是红色框的那个区域诶,大概是那么大的一个box,说只要你打中那个box,我就算你打中了。
这个听上去大家是不是呃好像有点反直觉啊,这么高级的一个设计游戏,原来这么粗暴的就判断了我能打中,这个,让我极大的激发了我写外挂的这个这个动力,对不对,但是再次再次说一遍啊,外挂本身是违法的啊。
大家不要去碰它,但是呢确实啊,但是我相信啊,他的防范的方法还有很多,包括现在最新的守望二,我不知道他用了什么技术啊,这至少是他自己公开资料讲师,我是这样去做他的。
这个就是这个这个服务器端的verification,所以这个里面反过来讲一件什么事情呢,就是说如果你选择了相信客户端,去做这个hit detection的话,在服务器端的检测检测呢。
我很多时候基本上是靠蒙的哈哈,我只能做一些呃,基本勉强能说得过去的这样的验证,然后其他的我只能交给这个,我相信这个客户端,但是其实没有那么简单,因为我们为了防止用户作弊。
其实我们会在本地做很多的这个防作弊措施,后面会具体的讲,那么所以这个其实就是这个在客户端做检测的,这个方法,那这个方法的话呢,其实刚才也讲了,就是它的好处是什么呢,就是非常的高效,非常的准确对吧。
那你真的打的很爽,对不对,第二个的话呢,他真的还高效,为什么高校呢,因为他很多计算比较麻烦的计算机,全部在本地做完了,所以在服务器那边其实是比较轻松的,你想要做一个RECOSTING。
这个是很快的嘛对吧,但是效率很高,但是呢他最大的问题就是,我们讲的就是非常的这个不安全,因为客户端一旦被破解,或者说网络包一旦被破解的话,它就非常麻烦,那真的要做很多特殊的处理。
我才能勉强避免你的作弊啊,这里面我给大家讲一个非常简单的这种,如果是客户端检测游戏怎么去作弊的方法,这个方法是这样的,有一种方法叫luck switch,什么意思呢,就是说哎呀这个这个叫小朋友学坏了啊。
就是你可以用软件也好,用硬件,硬件的话,你把你的网络当场给断一下,这样他就没有新的包过来了,没有新的抱过来的时候,你面前的敌人是不是就暂时停了一下,对不对,诶,你这个时候一枪一枪的往你面前。
时间静止的敌人爆头,然后呢再过比如说一秒钟或者是0。5秒,把这个网络再接回去,诶,这个时候因为这个时间很短嘛,所以一般服务器不会判断你掉线对吧,但是你完美的完成了这个一次的,这个这个什么枪毙爆头诶。
这个时候服务器导弹就受到了一个,相对真实的说,你把人家爆头的这样的一个一个一个现状了,特别是如果对方移动没有那么大的时候,唉你真的可以这么干的,所以说这其实哈是客户端,这个就是检测的时候。
真的是玩家有各种各样很奇怪的骇客的方法,比如说还有一个方法,就是比如说我们弹药量是有限的对吧,但是的话呢客户端那个发出这种hit的,有的时候可以如果写的不好的话,它可以用无限的弹药。
我们自己写写那个online游戏的时候,我们也会遇到这样的一个bug对吧,也是因为客户端那个detection本身的不可靠性,所以说这其实就是cosk detection的问题。
所以这其实是一个很不安全的一个方法,那如果客户端很不安全,那我们怎么办,我们把这个击中命中检测放到服务器端,那这里面就出现了一个很有意思的问题,就是说在服务器端你看到了这个人的位置。
一定会比你在我本地看到的这个这个这个慢,对吧啊快,因为服务器端这个老哥已经跑到,比如说跑进掩体了,但是在我的世界里面,他还没有跑进掩体,对不对,这个时候我我看到这个世界这个人没有跑进你。
我想一枪把他毙了,但是的话呢服务器端说他已经跑进去了,他认为你这箱开的是无效的,那尤其是我要进行精准瞄准的,这样的一个射击游戏的时候,是不是你永远也打不中移动中的目标呢,对吧就是如果放在客户端。
我对方在移动,我能击中它,但是如果在服务器端的话,只要对象在运动,除非我知道服务器端,那个人真实的位置已经往前走了,否则的话我是打不中他的,这其实就是这个啊,放在服务器端一个最基本的一个问题。
那这个问题怎么解呢,哎这里面的话呢,就要引入一个大名鼎鼎的概念了,叫lack composition,延迟补偿,这个听上去这个名字听上去就非常的高端,叫延迟补偿对吧,我补偿个啥呢。
其实他补他的想法其实非常的简单,就是说当我收到了一个客户端,说我开枪了的一个指令的时候,我不是说马上把我现在假设我是服务器啊,我收到了说诶那个张三开了一枪,想打李四对吧,没问题,我当时我不知道他要打谁。
我就说张三开了一枪,我知道他设计的位置,设计的点设计的方向给我了,这个时候呢我不会简单的说,因为我现在的状态,就是现在状态里面李斯的位置去检测一下,有没有被这个弹道给击中,因为什么呢。
因为如果李四在动的话,在张三那边的这个李斯的位置,肯定比我这边感受到的位置要慢,为什么呢,因为李四的位置是要通过我才同步给他的,对不对,可能会慢个100ms以上对吧,那么好,那怎么办,诶,公平起见。
我把这个我这里的状态的时钟往回拨,拨回倒回去,100ms,100ms之前,李四在哪,哎,我这个时候跟这根射线进行检测,如果我发现我这边存在一秒100ms钟之前的,这个李斯的位置的时候。
真的能被他打中的话,我认为张三同志,你打的是对的,是这个这句话用更简单的话一起解释,就是说我猜测在每一个shooter开枪者的时候,你开枪的那一瞬间,你的世界是什么状态,虽然我作为一个服务器。
我并不知道你是真想要,但是我可以根据延迟,根据我们的算法,我可以去猜测这件事情,所以这个都想这个思想叫什么呢,叫做延迟补偿,但是大家想想看,如果我想去真的实现这样的一个延迟补偿的,这个算法的话。
是不是我有个前提,就是说在我的服务器上,我的server的这个这个世界的这个state的,这个每一个tick的时候,我是不是要对state的做一个快照对吧,我要存一段时间,这样的话。
比如说唉有的客户端是50ms,有的客户端是100mm,有的客端150ms,我呢都能够找得到对应的过去的人,所以说呢其实这个对服务器里面有个要求,就是说我要对世界各个这个状态进行一个快照。
我要形成一个buffer,这也是延迟补偿的一个基础,好那更具体的讲这个case的话,这张图看的就比较清楚了,就是说哎当这个服务器在这个位置的时候,我蓝色的是我现在这个在跑的人,就是我的目标人物对吧。
红色的就是那开枪的坏人对吧,他要打打别人,那么蓝色它开始在从位置一移动的时候,实际上它首先到我的这个服务器的话,已经有一个延迟了对吧,哎然后呢再传到他的rap段,就是那个红色的那个。
就是要开枪的那个地方的话,又有一个延迟,其实呢还不只能延迟,大家记住,如果我们之前讲过是PS游戏,很多时候是什么,是内插值对吧,内插值是什么呢,我还要去等一段时间,我对你的位置进行插值之后。
我才能得到你的位置,所以这样的话呢,其实这个时候我在红色那个地方,我看到的时间其实已经很落后了,好那个红色那个玩家说,OK我看到你了,我开始开枪了,砰开枪开枪的时候呢。
诶这个开枪的消息也不是立刻马上能告诉server了,他还得经过一个延迟才能传到我的server,所以当server最后收到那个红色的玩家开枪的时候,你发现没有,蓝色玩家目录到那个点的时间。
已经差了10万8000里了,那好那那个蓝色玩家你真的你到哪,我们不care对吧,这个这个我们能理解,但是的话呢这个就是说至少在我server里面的话,我也跟我的状态也差了10万8000里。
所以说这个时候如果用server那边的,这个蓝色玩家的位置,去做那个那个他的那个就是射击机检测的话,肯定是错的,所以那个composition的这个核心思想是什么,诶。
我要把我的时间就rewind time,我把时间倒回什么呢,就是我当前的时间减去你的各路的latency对吧,还减去什么呢,你客户端如果采取的内插值,因为我们知道你们因为我们是同一个游戏。
所以我知道你内插值用的什么算法,所以我知道你的interpretation offset是多少,所以我就可以把时间拨回到那个点,然后我就能猜测在你开枪的那一瞬间,在红色的那个客户端,你看到的位置在哪里。
这个听上去稍微有那么一丢丢的抽象,但大家只需要知道他的思想就可以了,其实这个思想,其实我觉得还是一个蛮聪明的一个思想,这里面这张图就是一个真实游戏的一个案例,就是说其实那个角色就是你拿着枪的。
就是诶蓝色那个玩家我要开枪了,对不对,诶那个红色的玩家呢,就是我在我看过了那个红色玩家是一啊,它真实的其实呢已经跑到了那个前面一点点了,但是的话呢在服务器上,这里面的话就是说啊,如果我没记错的话。
因为字看的不是特别清楚,那个如果red的话,其实是那个你的你的,当前的那个就是玩家在服务器端,我倒回去的时候所在的位置,而红色的话呢,实际上是诶在你射击者的世界里面,看到他的位置。
所以这样的整个时间我倒回去的时候,你会发现如果网络的波动基本上是稳定的,就是网络不会lens,也不会一直在波动,那么我们对服务器的这个ticking的周期,和客户端TK的周期,包括客户端进行差值的算法。
是全部对焦过的话呢,其实la composition是能给你一个,相对好的一个结果的,这也是为什么就是说像那个就是有些设计游戏,敢采用这种就是说啊这个状态同步的方法去做,其实也是有基于这样的一个。
就是啊敢敢采取这种就是hit registration,就是服务器端做设计检测的原因,就是因为我能够对你客户端的状态进行补偿,那这个补偿有个很大的好处,就是说如果客户端进行一些攻击的时候。
诶我可以选择无视对吧,你比如说刚才我讲的那个你突然拔网线的话,我也不管你要拔就拔,对不对,反正我预测的那个延迟就是那样的,你肯定是打不中的,对所以说这是like composition的话。
一个很核心的一个思想,那这里面有个细节,就是说你就是根据你不同的算法,比如说你是用内插值呀,外插值呀,其实在这个LOCAUATION里面,你都要单独的处理,实际上大家如果真的去写一个,实战的游戏的时候。
你会发现这里面要处理的情况真的非常的多,比如说你用了外插值,还再加上本地的一些物理检测,对不对,诶这个方法好像又变得更复杂了对吧,那这里面我就不展开了,反正我自己要写这个东西的话,我也写的头疼。
肚子疼对好,所以的话呢这个地方的话就是诶,尝试已经解决了我们所有的问题,是我们很开心了,但是呢实际上我为什么要讲说has registration,到目前为止,我不认为它完美地解决了。
比如说这里面一个最经典的问题就是cover,就是掩体问题对吧,掩体问题分两种,第一种是什么呢,我现在在开阔地,我要躲进掩体,这个时候呢你会发现一个很有意思的事情,就是说我觉得我已经躲到掩体后面了。
大家如果玩一些设计游戏,你没有发现,我感觉我已经做了一个完美的躲避了,但是对我躲到掩体后面,被人家一枪打死了,就像一个视频中出现的这个情况,但是为什么呢,其实它还是由这个leg导致的。
就是说在对方的客户端里面,你还没有进掩体,所以他在比如说0。1秒,0。2秒开了一枪之后,你的位置已经发生变化了,但是他还是把你打死了,而且这个东西的话呢,因为有like composition对吧。
那服务器端,服务器端是以开枪人的那边的世界为准的,这是菲尔的,对不对,所以你就是被打死了,所以说在这样的一种情况,就是如果你躲进掩体的时候,实际上呢这是一个对开枪者有利的一种情况,对吧。
那么再讲一个第二种情况,很有意思的,就是说哎我现在我先躲在掩体后,我开始偷窥别人的时候,唉,因为由于legging的原因,其实我已经看到对面来了一个人了,但是呢因为我的位置还没有同步过去。
所以在他的世界里面,我还躲在掩体后面,他还看不见我,而且呢我那个时候无论是以发现他呀,还是这个开枪啊,其实我都会抢一个先手的优势诶,大家看到没有,这里面是不是有一个,如果对方用黑特瑞斯生的方法。
做这个这个这个做射击命中判定的时候,有一个大家想到了非常棒的一个作弊的方法,对你从掩体后面突然冒出来的时候,其实注意如果网络延迟比较大的话,你就是优势方,为什么呢。
因为对方可能在100ms之后才能看到你,但是你已经抢了一个100ms的先手了,所以其实在这个case里面的话,如果冲出来的人是picker对吧,那个在外面假卡住位置,打算mini的人叫holder的话。
那其实这个时候呢是冲出来的人,就是掩体后面冲出来的人,他实际上是有优势的,你发现没有,虽然我们讲了,那么多的luck composition的这个算法,但实际上在一个网络的这种延延迟的情况下。
他的这个这个宇宙啊,它其实是不对等的,在不同的SCENARO情况下,就是它实际上都会产生了,不同的优势方和劣势方,这也是为什么我们讲作为一个网络游戏,其实非常复杂的一个原因,那么这里面的话呢。
比如说我们做一个专业的一个职业的设计,比如FPS游戏的一个竞技比赛的话,一般我们都会选择用局域网,要把延迟控制的足够小,因为啊假设你的延迟只有十几毫秒的话,这个应该还好。
但是呢其实这里面还要做一件事情是什么呢,就是说我们会哦这里面我这样把它去掉了,就是我们会怎么,我们比如说一个专业的cs的,一个一个一个一个server的话。
我们可能会把server的这个frame rate,这个这个tick rate调得非常高,这样的话,尽可能把每一个环节的延迟都会降下来,这样对双方的选手来讲相对公平一点,所以同学们现在就能理解说。
为什么就是如果网络对战游戏做不好的话,很容易就会出现就是某一种操作,它必然有先天优势,也是这个道理,但是呢hit registration呃,他特别是like composition的话。
还是一个目前为止最为重要的一种,就是网络同步,这个在网络情况下去同步击中判定的一个方法,O那么这里面还有没有别的方法呢,其实还有一些方法,比如说我们叫做这个能不能用一些hack的方法。
能够让大家的命中变得更加的符合我们的认知,有一个最简单的方法是什么呢,哎叫前摇,这个大家肯定没有听这个这个词,如果玩游戏的同学们一定知道我在讲什么对吧,就是当我发动攻击的时候。
假设我让角色播放一个非常炫酷的,这个起手动作,哎其实你会觉得这是个表演对吧,而且你也觉得非常的合理,但是呢就那么几帧的起手动作,给我们的网络同步争取了,比如说50ms,100ms。
这样的话也能够非常有效的降低,就是在网络的波动情况下,或者网络延迟情况下,我们导致了就是客户端和服务器端状态不同步,的这个latency,所以说很多游戏,特别是啊我们在动作游戏的时候。
我会建议就是说大家会做一些设计的前摇,因为前摇这件事情能够给网络同步争取时间,当然了,这个地方要去单独的处理,那么另外一种呢,就是让大家觉得感觉好的方法是什么呢。
就是虽然我用的还是这个这个服务器端判定的,这种hate registration,但是呢我在本地首先检测觉得你命中了诶,我假设命中的时候,我先让他播放一个巨大的这个雪花的,这种particle出来对吧。
或者一些什么特效,这个时候你在本地的感觉就打击更好,为什么呢,因为否则的话你老等服务器回来的话,你开一枪,你觉得你打中别人了,但是呢你的消息到服务器,服务器算完之后再回来,可能是150ms。
200ms钟的时,已经0。2秒之后了,你就会觉得那个感觉很奇怪,就像塑料打空气的感觉诶,所以我在本地先让你把播放出一个,比如说巨大的雪花啊,或者说我让你出现一个,就是说这种这个暴击的这个数字啊。
我上次不讲暴击,可以在本地做预算,预算嘛对吧,但是呢这里面有一个细节,就是说这里面所有你想要的特效,这些东西呢它都是让你感受好一点,但是真实的伤害数字我们叫做结算诶,它还是以服务器的计算为准。
所以这样的两种方法的话呢,能够让大家的感受会好很多,其实我个人特别推荐的,如果你做一款动作游戏的这个引擎的话,一定要鼓励大家多做前摇,因为前摇的话确实能给网络同步,这个这个这个这个就是说争取很多时间。
但是钱要做长了,大家都感受什么,哎呀这个英雄这个技能起手实在太慢对吧,所以的话世界上没有免费的午餐。