腾讯邓君:《王者荣耀》翻过的同步技术相关的三座大山
在Unity舉辦的Unite 2017上海開發(fā)者大會(huì)中,案例分享專場(chǎng)受到了業(yè)內(nèi)的高度關(guān)注,眾多行業(yè)領(lǐng)軍人物針對(duì)過往的成功案例慷慨的分享了開發(fā)過程中的經(jīng)驗(yàn)教訓(xùn),而《王者榮耀》項(xiàng)目組技術(shù)總監(jiān)鄧君的分享則無疑成為了焦點(diǎn)中的焦點(diǎn)。
雖然《王者榮耀》如今已經(jīng)成為席卷一切的國(guó)民級(jí)游戲,但其在問世之初卻經(jīng)歷過一段鮮為人知的調(diào)優(yōu)期,而當(dāng)時(shí)騰訊對(duì)于這款產(chǎn)品的重視程度和期待值也遠(yuǎn)不及旗下的其他MOBA產(chǎn)品。
這款作品為何最終能成為MOBA手游標(biāo)桿式的存在?其開發(fā)過程中究竟經(jīng)歷了哪些困難和挑戰(zhàn)呢。鄧君在他的分享中給出了答案。
以下為星游社整理的演講精華:
這次的主題主要是講一下王者榮耀從立項(xiàng)之初經(jīng)歷的慘淡時(shí)期到華麗的翻盤,這里不管碰到技術(shù)方面的問題,還是游戲方向上的改變,我是技術(shù)出身的,整個(gè)課題也是技術(shù)面的,會(huì)重點(diǎn)介紹王者榮耀和現(xiàn)在見到大部分不同的技術(shù)方案,它實(shí)際原理、問題和優(yōu)化的思路。
先簡(jiǎn)單自我介紹一下,我是2004年加入騰訊,在騰訊做了4年多的應(yīng)用層面開發(fā),還包括web各種各樣后臺(tái)都做過,經(jīng)歷比較豐富,在2009年我回成都,剛好成都的崗位也就只有游戲部門是比較合適的,就轉(zhuǎn)行做游戲了。在成都這邊,參與過一個(gè)《QQ封神記》的開發(fā),從封神記出來之后,又開發(fā)了一款游戲,這款游戲開發(fā)了三年多,游戲從1.0、2.0、3.0,這個(gè)時(shí)候再轉(zhuǎn)型做手游,直接做的王者榮耀。
我們介紹一下王者榮耀,現(xiàn)在了解王者榮耀或者在玩王者榮耀的人確實(shí)比較多,但是我們?cè)?jīng)也沒有想過王者榮耀有這樣的結(jié)果。當(dāng)時(shí)端游很久都沒有做出來成績(jī),業(yè)績(jī)和收入都面臨比較大的問題。霸三國(guó)做到1.0之后,要操作多個(gè)單位,2012、2011年的時(shí)候,大家覺得特別費(fèi)操作,要控制很多單位的游戲,操作起來很難,一開始可以操作5支單位然后變成3支持,3支完了覺得也很痛苦,這個(gè)游戲策略性很強(qiáng),慢慢把5個(gè)單位的技能合在一個(gè)身上。你要做創(chuàng)新,你要脫穎而出,是很難的事情。
在2014年年底的時(shí)候,2015年我們準(zhǔn)備開一個(gè)手游團(tuán)隊(duì)。為什么開手游團(tuán)隊(duì)?國(guó)內(nèi)環(huán)境里面,基本上都在開發(fā)手游,能夠繼續(xù)開發(fā)端游或者要準(zhǔn)備立項(xiàng)端游的非常少,包括騰訊也就是2、3款端游在開發(fā),端游還是有希望的,開發(fā)的團(tuán)隊(duì)比較少,手游也是一個(gè)機(jī)會(huì),希望在2015年把我們的霸三國(guó)端游在手游上呈現(xiàn)。這個(gè)時(shí)候我們進(jìn)行了一個(gè)初期Demo的驗(yàn)證,Demo驗(yàn)證只有三個(gè)人,引擎的、框架的、后臺(tái)的,大概做了兩周到三周,把Demo做出來,里面有基本的進(jìn)游戲、選人,然后可以釋放技能,正常的戰(zhàn)斗,到結(jié)算。但是是用Unity來做的,兩、三周做完之后,覺得Unity很好用,開發(fā)確實(shí)比較高,簡(jiǎn)單的先這樣,2015年才開始進(jìn)行一個(gè)真正的獨(dú)立招聘20、30人做手游項(xiàng)目,當(dāng)時(shí)是這樣的想法。2014年年底的時(shí)候,我們制作人去公司開會(huì),當(dāng)時(shí)這是一個(gè)非常明智的決策,我們需要馬上暫停端游的開發(fā),直接做手游。就是這樣的一次決策,真正的是扭轉(zhuǎn)了我們整個(gè)團(tuán)隊(duì)的命運(yùn)。如果晚一年,可能今天的游戲就是另外一個(gè),應(yīng)該不是王者。
為什么選擇Unity引擎
我們從端游轉(zhuǎn)型做手游,做手游肯定要面臨選擇什么樣的引擎,采用什么樣的方案進(jìn)行手游的開發(fā)。當(dāng)時(shí)的環(huán)境,周邊包括騰訊還有成都的創(chuàng)業(yè)團(tuán)隊(duì),基本上都是Unity,我都不知道,大概在2013、2014年出來很多游戲都是Unity,我們做Demo的時(shí)候,也會(huì)選擇大家用的,已經(jīng)有產(chǎn)品進(jìn)行驗(yàn)證了,同時(shí)我們也考察它適不適合我們的團(tuán)隊(duì)。Unity我們當(dāng)時(shí)做Demo的理解,它確實(shí)對(duì)中小團(tuán)隊(duì),包括作為一些大型項(xiàng)目,它有幾個(gè)比較明顯的優(yōu)勢(shì)。
1、 在兩三周你就可以做出Demo,易上手是一個(gè)非常大的優(yōu)勢(shì),在座可能都理解。
2、 另外,它的工具都是很完善的,能夠做到一站式解決,你不需要在這里面下載工具,那里面額外補(bǔ)充一些插件。
3、 另外還有它插件資源很豐富,我們從最開始做Demo的時(shí)候,基本上都是找一些我們可以用來驗(yàn)證我們想法的,它肯定可以加快我們開發(fā)的效率。
4、 上面這三點(diǎn)加起來,是它非常明顯的優(yōu)勢(shì),開發(fā)效率特別高。
5、 還有跨平臺(tái),那是肯定的,它本是就是跨平臺(tái)的引擎。
6、 還有你能夠?qū)θ藛T的補(bǔ)充,非常容易,因?yàn)樵谥苓叞ㄉ鐣?huì)上招聘都很容易招聘到熟悉Unity的開發(fā)人員。
我們這邊直接對(duì)比以前自己做引擎,或者用過其他的引擎,從效率上來講,我們選擇了一個(gè)開發(fā)效率最高的引擎。這里面回過頭來,從端游轉(zhuǎn)換到手游是在2014年底,我們真正開始的時(shí)候在2015年3月份就進(jìn)行開發(fā),這個(gè)時(shí)候我們開發(fā)的周期短,我們需要盡快把手游做上線。我們本身霸三國(guó)開發(fā)大概有40、50個(gè)人,后面把周邊的兄弟部門都合并在一起了,里面有一些會(huì)Unity、會(huì)手游的,還有一部分沒有手游開發(fā)經(jīng)驗(yàn)的,組合在一起,形成了100多人的團(tuán)隊(duì),進(jìn)行了游戲的開發(fā)。
還有一個(gè)很重要的選擇,我們本身是一個(gè)網(wǎng)絡(luò)游戲。當(dāng)時(shí)在2013、2014年的時(shí)候,游戲在pvp上面比較弱,大部分是卡牌游戲、單機(jī)游戲,我們本身是一個(gè)端游,它的生命力包括趣味性也是很足的,我們做手游的目標(biāo),即使我們里面有PVE的闖關(guān)內(nèi)容,但是我們里面有最核心的東西還是PVP,讓玩家有真正的對(duì)抗,玩家與玩家有交流,體會(huì)到游戲的樂趣。
同步機(jī)制的抉擇
既然選擇了pvp,它可能就是一個(gè)網(wǎng)絡(luò)游戲,網(wǎng)絡(luò)游戲我們選擇用什么樣的同步機(jī)制呢?最常見的應(yīng)該是cs狀態(tài)同步,我們端游也是這樣做的。后面我們?yōu)槭裁磿?huì)選擇幀同步,后面再說。
先看一下狀態(tài)同步的優(yōu)缺點(diǎn)。
1、 它的安全性非常高,基本上外掛沒有什么能力從中收益,基本上都是服務(wù)器校驗(yàn)。
2、 另外狀態(tài)同步對(duì)于網(wǎng)絡(luò)的帶寬和抖動(dòng)包有一個(gè)更強(qiáng)的適應(yīng)能力,你有一個(gè)輸入延遲200、300后面又好了,你其實(shí)感受不出來它不太舒服的地方
3、 在開發(fā)游戲過程中,它的斷線重回比較快。如果我的游戲崩潰了,回來之后需要服務(wù)器把所有重要對(duì)象的狀態(tài)再同步一次過來,重新再創(chuàng)建出來就可以了。
4、 它的客戶端性能優(yōu)化也比較明顯。客戶端在做性能優(yōu)化的時(shí)候,它可以做裁剪,我看不到的角色我可以不用創(chuàng)建,也可以不用對(duì)它進(jìn)行運(yùn)算。
說完了優(yōu)點(diǎn),再說一下我認(rèn)為的缺點(diǎn)。
1、 一個(gè)就是開發(fā)效率要相對(duì)幀同步差一些,很多時(shí)候你要從服務(wù)器客戶端的每一個(gè)角色對(duì)象的狀態(tài)之間保持一致,你很難做到它是一致的,包括客戶端和服務(wù)器端更新的頻率,他們對(duì)優(yōu)化的一些裁剪,包括網(wǎng)絡(luò)的一些抖動(dòng),你要讓每一個(gè)狀態(tài)在客戶端有一個(gè)同步,是比較難,你要想調(diào)試這些東西,出現(xiàn)的漏洞、不一致的現(xiàn)象,調(diào)試周期比較長(zhǎng),想要達(dá)到優(yōu)化好的水平,也是比較難的。
2、 它比較難做出動(dòng)作類游戲打擊感和精確性。比如說你要做一個(gè)人是射擊類,他的×××每秒鐘要產(chǎn)生幾十顆,基于狀態(tài)同步是比較難的事情,因?yàn)樵诤芏虝r(shí)間會(huì)產(chǎn)生很多角色,要通過創(chuàng)建、銷毀包括位置和運(yùn)算。
3、 它的流量會(huì)隨著游戲的復(fù)雜度,角色的多少而增長(zhǎng)。你做手游,也是想追求你在3G、4G也能夠玩pvp,對(duì)你付費(fèi)流量的消耗,我們希望能夠做到一個(gè)比較好的水平,不希望能夠打一局游戲需要消耗幾十兆的數(shù)據(jù)流量。
我們?cè)倏匆幌聨?#xff0c;大部分人應(yīng)該還是了解的。最初大家玩的心計(jì)、魔獸3都是幀同步,他們是基于局域網(wǎng),網(wǎng)絡(luò)非常好,也不需要服務(wù)器,他們直接用新型的網(wǎng)絡(luò)就能夠搞定。幀同步的優(yōu)點(diǎn)有幾個(gè):
1、 開發(fā)效率比較高,為什么說開發(fā)效率比較高?如果你整體的框架是驗(yàn)證通過,你把它的缺點(diǎn)解決了的話,你完全開發(fā)思路就跟寫單機(jī)一樣,你只需要遵從這樣的思路,盡量保證性能,該怎么寫就怎么寫,相對(duì)于我們經(jīng)驗(yàn)來說,以前要在狀態(tài)同步下面做一個(gè)復(fù)雜的技能,有很多段位的技能,也許可能要開發(fā)好幾天,才能有一個(gè)稍微過得去的結(jié)果,可能在幀同步下面,英雄做多段位技能很可能一天就搞定了。
2、 它的打擊感確實(shí)比較強(qiáng),打擊感強(qiáng)除了我們說的各種反饋、特效、音效,還有它的準(zhǔn)確性。你游戲里面看到這些揮舞的動(dòng)作,它能夠在比較準(zhǔn)確的時(shí)刻就能夠有反饋,包括它的密度可以做到很高的頻率,是狀態(tài)同步比較難做的。
3、 它的流量消耗是穩(wěn)定的。大家應(yīng)該看過星際的錄像,它的錄像只有幾百K,這里面就是網(wǎng)絡(luò)流量里面全是驅(qū)動(dòng)游戲的輸入序列。幀同步只會(huì)隨著玩家數(shù)量,流量才會(huì)增長(zhǎng),如果玩家固定的話,流量不管你的游戲有多復(fù)雜,你的角色有多少,它基本上都是穩(wěn)定的。這點(diǎn)延伸的好處是可以做觀戰(zhàn),錄像的存儲(chǔ)、回放,包括基于錄像文件后續(xù)的處理都比較容易做。
說了這么多優(yōu)點(diǎn),它肯定也有缺點(diǎn)。
1、 最致命的是網(wǎng)絡(luò)要求比較高,如果你的網(wǎng)絡(luò)稍微有抖動(dòng),它是一個(gè)鎖幀的,如果有這樣的抖動(dòng),一段時(shí)間調(diào)用次數(shù)是不穩(wěn)定的,網(wǎng)絡(luò)命令的延遲會(huì)有擠壓和舒展。
2、 它的反外掛能力很弱,幀同步邏輯都在客戶端里面,你可以查得到它有沒有作弊。游戲的邏輯是在客戶端,你可以修改它。為什么王者敢用這樣一個(gè)東西,當(dāng)時(shí)選型的時(shí)候,半年的開發(fā)周期需要做出來,要做上線,要有幾十個(gè)英雄,有時(shí)間的壓力。另外一個(gè)這樣一個(gè)游戲類型,不像成長(zhǎng)類的游戲,它是基于單局的,單局你修改這個(gè)東西,頂多影響這一局的勝負(fù),不會(huì)存檔,你刷多少錢穿比較好的裝備,這本身是一個(gè)弱成長(zhǎng)的游戲,我們認(rèn)為它不是一個(gè)致命的缺點(diǎn)。你在這上面可以做到收益不明顯,你做完之后我們可以發(fā)現(xiàn)你有沒有作弊,作弊了一樣有懲罰。反外掛雖然缺點(diǎn)在,在王者這樣游戲類型下面不是特別明顯。
3、 斷線重回時(shí)間很長(zhǎng),我估計(jì)下面有非常多的玩家,也碰到過如果你玩著玩著最后閃退你回來有多痛苦,第二個(gè)100%等到完成你游戲進(jìn)去了,游戲也結(jié)束了,這個(gè)幀同比是比較致命的,每一幀的鹽酸最后才能算到正確的狀態(tài)。
4、 它的邏輯性能優(yōu)化有很大的壓力。大家應(yīng)該沒有見到哪一款大型游戲用幀同步來做的,每一個(gè)邏輯對(duì)象都是需要在客戶端進(jìn)行運(yùn)算。如果你做一個(gè)主城,主城里面有上千人,上千人角色雖然看不到它,但是你需要對(duì)它進(jìn)行有效的邏輯運(yùn)算,這就是它無法做非常多的游戲?qū)ο笮枰碌挠螒驁?chǎng)景。
為什么我們選擇了幀同步而放棄了狀態(tài)同步呢?前面提到它兩個(gè)優(yōu)點(diǎn)缺點(diǎn)是相對(duì)的,這邊的優(yōu)點(diǎn)對(duì)于那邊來說就是缺點(diǎn)。對(duì)于我們手游立項(xiàng)的時(shí)候,最重要就是時(shí)間。當(dāng)時(shí)市面上正在開發(fā)的包括騰訊內(nèi)部的都不止王者一款在開發(fā),大家都在爭(zhēng)取上線的時(shí)間,我們可能會(huì)選擇一個(gè)開發(fā)時(shí)間周期最短的方案。然后我們做端游也有一個(gè)深刻的體會(huì),做有趣的英雄,有趣的技能,它在狀態(tài)同步上面很難調(diào)出一個(gè)比較滿意的效果。它的優(yōu)點(diǎn)包括我們自己對(duì)于狀態(tài)同步的體會(huì)上面,最后我們依然選擇幀同步的方案。選擇幀同步方案,確實(shí)現(xiàn)在回過頭來講,我們把缺點(diǎn)優(yōu)化掉規(guī)避掉,它帶來的好處是比較明顯的。我們的游戲比較好玩,除了英雄的設(shè)計(jì)包括整個(gè)技能的感覺,還有很重要的一點(diǎn),它確實(shí)在做一些非常有特色的英雄,它的技能、反饋、體驗(yàn)上面都是做的不錯(cuò),這是基于幀同步技術(shù)方案的優(yōu)勢(shì)。
開發(fā)過程中面臨的三座大山
我們選擇了方案之后,當(dāng)時(shí)覺得很high,覺得這樣一個(gè)技術(shù)方案開發(fā)起來得心應(yīng)手,效率如此之高,做出來的效果也很好。但是它也有好的一面,也有壞的一面,技術(shù)測(cè)試版本上線后質(zhì)量不好,其中技術(shù)層面應(yīng)該就是這上面的三座大山。
第一個(gè)同步性,同步性這塊容易解決,其實(shí)也解決了。
第二個(gè)也是最大的一個(gè)問題是網(wǎng)絡(luò)問題,幀同步它的網(wǎng)絡(luò)問題導(dǎo)致我們對(duì)它技術(shù)方案的原理沒有吃透,碰到了一些問題,那時(shí)候游戲感覺延遲很重,畫面卡頓,你明顯感覺走路抖動(dòng)的現(xiàn)象。
第三個(gè)是性能問題,這個(gè)問題始終存在,也一直在優(yōu)化。
先看一下第一座大山,最容易解決的,說一下幀同步的技術(shù)原理,相當(dāng)簡(jiǎn)單,10、20年前就有了,它要一個(gè)相同初始的狀態(tài),后面你需要有一個(gè)相同的輸入,我往下一幀執(zhí)行,執(zhí)行的時(shí)候我所有代碼的流程,大家走的是一樣的,有了相同輸入之后,輸入包括第一幀、第二幀、第三幀,有了輸入然后要執(zhí)行相同流程,大家走的一模一樣,這個(gè)結(jié)果調(diào)用完了以后,又有一個(gè)新狀態(tài),下一個(gè)狀態(tài)大家又有一樣,完成了循環(huán),相同的狀態(tài),相同的流程,不停的這樣循環(huán)下去。這個(gè)原理雖然簡(jiǎn)單,但是你要去實(shí)現(xiàn)它的時(shí)候,還是會(huì)有很多坑。
右邊寫的是實(shí)現(xiàn)要點(diǎn),這是我們?cè)诮鉀Q第一座大山經(jīng)驗(yàn)的總結(jié),也是我們實(shí)際開發(fā)過程當(dāng)中做的事情。
1、 我們所有的運(yùn)算都是基于整數(shù),沒有浮點(diǎn)數(shù)。浮點(diǎn)數(shù)是用分子分母表達(dá)的。
2、 我們可能還會(huì)用到第三方的組件,幀組件也要需要進(jìn)行一個(gè)比較嚴(yán)格的甄別。我們本身用的公司里面關(guān)于時(shí)間軸的編輯器里面,最初也是是浮點(diǎn)數(shù),我們都是進(jìn)行重寫改造的。
3、 你初次接觸幀同步里面出問題,就是寫邏輯的時(shí)候和本地相關(guān)、和“我”相關(guān),這樣就導(dǎo)致走到不同分支,真正客戶端跟邏輯的話,要跟我這樣一個(gè)概念無關(guān)。
4、 還有隨機(jī)數(shù),這個(gè)要嚴(yán)格一致。這是實(shí)現(xiàn)的要點(diǎn),嚴(yán)格按照這上面的規(guī)則寫代碼還是有可能不同步,本身就很難杜絕這樣的問題。
5、 真正一個(gè)比較重要的是開發(fā)者要提升發(fā)現(xiàn)不同步的能力,什么時(shí)候不同步了,不同步你還要知道不同步在什么點(diǎn),這是最關(guān)鍵的。你需要通過你的經(jīng)驗(yàn)和總結(jié)提升這樣的能力。這個(gè)能力還是通過輸出來看不同客戶端不同輸出,找到發(fā)生在什么點(diǎn)。特別是在概率比較低。
比如在《王者榮耀》中,我們看到不同步的現(xiàn)象應(yīng)該是這樣,有人對(duì)著墻跑,你看到就是你和別人玩的游戲是不一樣的,進(jìn)入平行世界。
最開始測(cè)試的時(shí)候,我們希望不同步率達(dá)到1%,就是100局里面有1局出現(xiàn)不同步,我們就算游戲合格,其實(shí)對(duì)于這么大一個(gè)體量游戲來說是有問題的,經(jīng)過我們不停的努力,現(xiàn)在是在萬分之幾。一萬局游戲里面,可能有幾局是不同步的。這個(gè)問題不一定是代碼原因或者沒有遵循這些要點(diǎn)寫出來的,包括你去修改內(nèi)存,包括你去加載資源的時(shí)候,本地資源有損害或者缺失,或者是異常。異常說白了,你沒有辦法往下執(zhí)行,大家走了不同分支,這都可能引起最終是不同步的。如果你不同步概率比較低,這種萬分之幾概率的時(shí)候,很難通過測(cè)試來去還原,去找到這樣不同步的點(diǎn)。
最開始我們游戲出現(xiàn)不同步的時(shí)候,就是周末玩家開黑多的時(shí)候,隨著你的概率越來越低,基本上你就自己還原不出來了,只能依靠玩家?guī)湍氵€原這樣的場(chǎng)景,來分析這樣的不同步。
同步性遵循這樣的要點(diǎn),按照這樣的思路來寫,加上你不同步定位的能力,有了監(jiān)控手段能夠去發(fā)現(xiàn),這個(gè)問題其實(shí)就解決了。解決之后,你就可以好好享受幀同步的開發(fā)優(yōu)勢(shì)。
第二座大山就是網(wǎng)絡(luò),技術(shù)測(cè)試版本出臺(tái)的時(shí)候,延遲非常大,而且還是卡頓,現(xiàn)在看一下幀同步里面比較特別的地方。幀同步有點(diǎn)像在看電影,它傳統(tǒng)的幀同步需要有buffer,每個(gè)玩家輸入會(huì)轉(zhuǎn)發(fā)給所有客戶端,互相會(huì)有編號(hào),第幾幀,第幾幀的輸入,假如說我現(xiàn)在收到第N幀,如果我收到第N+1幀的話,N幀這一幀我是可以執(zhí)行的,是這樣一個(gè)情況。服務(wù)器會(huì)按照一定的頻率,不同的給大家同步幀編號(hào),包括這一幀的輸入帶給客戶端,如果帶一幀給你的數(shù)據(jù)你拿到之后就執(zhí)行,下一幀數(shù)據(jù)沒來就不能執(zhí)行,它的結(jié)果有可能你網(wǎng)絡(luò)非常穩(wěn)定,絕對(duì)理想值的情況下還好,現(xiàn)實(shí)網(wǎng)絡(luò)不是這樣的。幀同步要解決問題就是有buffer,以前有動(dòng)態(tài)的buffer,它有1到n這樣的緩沖區(qū),根據(jù)網(wǎng)絡(luò)抖動(dòng)的情況,收入然后放到隊(duì)列里面。這個(gè)buffer的大小,會(huì)影響到這兩個(gè)東西,一個(gè)就是延遲還有卡頓。如果你的buffer越小,你的延遲就越低,你拿到以后你不需要緩沖等待,馬上就可以執(zhí)行。但是如果下一幀沒來,buffer很小,你就不能執(zhí)行,最終導(dǎo)致的結(jié)果你的延遲還好,但是卡頓很明顯。你會(huì)調(diào)到幀同步的buffer,假如我們認(rèn)為網(wǎng)絡(luò)延遲是1秒,你抖動(dòng)調(diào)到1秒,那得到的結(jié)果雖然你畫面不抖動(dòng)了,但是你的延遲極其高。最壞的網(wǎng)絡(luò)情況都考慮進(jìn)去,buffer足夠大,跟看視頻是一樣的,平行的東西,看你調(diào)大條小。一些局部的措施我們都做過,都是一樣的問題。
我們?cè)趺磧?yōu)化卡頓這方面呢?本身剛才也提到了,它應(yīng)該幀同步有buffer,這個(gè)buffer可以是1也可以到n,我們要解決我們的延遲問題,我們就讓buffer足夠小,最后我們做到buffer是零,它不需要buffer,服務(wù)器給了我n,馬上知道是n,我收到n,我知道下一次肯定是n+1,所以我收到n之后馬上就把n這一幀的輸入執(zhí)行了,下一步可能就涉及到了為什么不卡頓了,畫面不抖動(dòng)了,是最后一條,是本地插值平滑加邏輯與表現(xiàn)分離。客戶端只負(fù)責(zé)一些模型、動(dòng)畫、它的位置,它會(huì)根據(jù)綁定的邏輯對(duì)象狀態(tài)、速度、方向來進(jìn)行一個(gè)插值,這樣可以做到我們的邏輯幀率和渲染幀率不一樣,但是做了插值平滑和邏輯表現(xiàn)分離,畫面不抖了,延遲感也是很好的。做了這些,我們還做了TCP換成UDP,在手機(jī)下面,弱網(wǎng)的情況下,TCP很難恢復(fù),UDP本身作為游戲也有優(yōu)勢(shì),之前還用過其他的,沒有優(yōu)化到最后,不是很理想,最后用了UDP來做。整體來說,在網(wǎng)絡(luò)好的情況下,它延遲也是很好的,在網(wǎng)絡(luò)比較差的情況下,做插值,網(wǎng)絡(luò)情況差的話,也是傳統(tǒng)cs的表現(xiàn),我們經(jīng)常見到角色A和B,有些客戶端A在左B在右,有些是A在右B在左,幀同步邏輯上面AB之間的距離和坐標(biāo)都是完全一樣,但是畫面上看到他們可能會(huì)不重合,那就是你把它們分離之后的表現(xiàn)。網(wǎng)絡(luò)極其好的情況下,它應(yīng)該是重合的,但是在網(wǎng)絡(luò)差的情況下,可能會(huì)有些偏差。這是里面最重要的一塊優(yōu)化。
第三座大山是性能。下面是我們對(duì)性能優(yōu)化,本身幀同步邏輯上面在優(yōu)化上面存在一些缺點(diǎn),所有的角色都需要進(jìn)行運(yùn)算。這里面還是用的Unity,里面也有很好的特性,如果你想追求性能上的極致,有些東西你需要尋求好的方式。
第一是熱點(diǎn)的處理,我們是不用反射的,它都有GC性能開銷,你可能經(jīng)常會(huì)隱藏或者把它顯示出來,我們的做法里面,把對(duì)象的顯示隱藏放在不同的渲染層里面,盡量讓整個(gè)游戲幀率是平滑的過程。還有我們本身有自己的系統(tǒng),還有AI,這樣的一個(gè)游戲類型里面的角色比較多,你如果想要做比較好,它的AI是比較復(fù)雜的。要去優(yōu)化熱點(diǎn),我覺得就只有這三個(gè)步驟可以走。
從程序的結(jié)構(gòu)上面能找到更優(yōu)的,它的效果是最明顯的,如果你的結(jié)構(gòu)都是用的最好,就在挖掘局部的算法,調(diào)整你代碼的一些寫法。如果局部的算法都已經(jīng)調(diào)到最優(yōu)還是沒有什么辦法,那只有一條路,就是犧牲整個(gè)質(zhì)量,就是分幀降頻。
第二點(diǎn)是GC,這塊剛才說不用反射,還有裝箱和拆箱的行為也是盡量少用。Unity指導(dǎo)過我們的優(yōu)化,從GC上面的考慮,他們建議每一幀應(yīng)該在200個(gè)字節(jié)以內(nèi)是比較好的狀態(tài),其實(shí)很難做到,王者也是每一幀在1k左右,很難做到200。
第三是Drawcall,這些傳統(tǒng)的優(yōu)化手段大家都用的很熟了。
第四是裁剪,幀同步里面是不能裁剪的,表現(xiàn)里面我看不到的可以降低頻率或者不更新它,這在表現(xiàn)里面可以做的。
第五點(diǎn)是3DUI。《王者榮耀》的血條、小地圖上面疊的元素比較多,比較豐富,這塊我們用了31UI的方式來優(yōu)化,沒有用UGUI里面進(jìn)行血條方面的處理。我們也犧牲了一些東西,我們把所有東西都加載了,在游戲過程當(dāng)中,我們希望不要有任何IO行為,包括輸出我們都是要布局的。你處理的決策和復(fù)雜度,如果在一幀里面放出100顆×××,在放100顆×××的時(shí)候一定要掉幀的,一定要在力所能及的時(shí)候把這些東西做到極致。
前面提的是第一代,去年5月份以前做的優(yōu)化方案。5月份的時(shí)候我們還做了另外一件事情:GameCore。
首先,為什么覺得IOS比安卓高一些,本身一個(gè)是IOS的CPU架構(gòu)包括系統(tǒng)確實(shí)都優(yōu)化的比較好,另外我們用的Unity4.6,在IOS下面它本身效率高一些,在安卓端的機(jī)器各種各樣,性能也是千差萬別,我們只能用性能比較差的方式。因?yàn)楸旧硪呀?jīng)做到邏輯和表現(xiàn)是分離的,我們能不能把邏輯獨(dú)立出來,做成一個(gè)C++的東西,我們?cè)谌ツ觊_始這樣做了。做之前也測(cè)試過C++和Mono性能的差別,大概是2.5左右,本身我們的邏輯占比游戲消耗20%多,邏輯不是一個(gè)大頭,我們做了GameCore之后,還是有效的,幀率提升了2到3幀,花的時(shí)間很長(zhǎng)。整個(gè)時(shí)間大部分都消耗在了引擎和CPU的交互、調(diào)度,
其次,做GameCore最顯著的變化是我們以前邏輯上的GC沒有了,我們有自己內(nèi)存的管理、對(duì)象的管理,包括里面所有的容器類這些東西都是我們自己實(shí)現(xiàn)的,包括反射整個(gè)一套。它有了自己的內(nèi)存管理,它本身效率就比較高,其實(shí)還是一個(gè)比較明顯的優(yōu)勢(shì),
再次,有了GameCore之后,有很多應(yīng)用場(chǎng)景,這個(gè)東西就是玩法的服務(wù)器版本,應(yīng)用場(chǎng)景運(yùn)行服務(wù)器要做很多的分析,還有第三方使用都是可以的。
最后,GameCore可以做成一個(gè)多線程的話。
“王者”前方的路
我們接下來看一下我們后面可能打算考慮的一些事情。
第一,是我們想能不能在熱更新上面有所突破。因?yàn)橥跽哌@樣一個(gè)游戲類型,包括它的體量,我們對(duì)于性能有一個(gè)比較極致的追求,不會(huì)輕易使用腳本層面在性能層面本身就不是最好的。這個(gè)我們要去研究的就是熱更新,性能最好的方式。
第二,我們也在和硬件廠商溝通,他們其實(shí)也是希望游戲能夠真正發(fā)揮多核性能上的優(yōu)勢(shì),大部分的游戲在單核上面,把一個(gè)核吃的滿滿的,很多時(shí)候我們現(xiàn)在得出的結(jié)論,GPU性能也很強(qiáng),王者并沒有對(duì)GPU占滿,可能只用了30%,CPU反而吃的比較滿,吃滿以后它還有另外一個(gè)壞處,它的發(fā)熱、降頻,你如果用多線程、多核去盡量平坦,讓它不要處于高頻的工作方式,反而會(huì)有更好的效果。
第三,我們現(xiàn)在用Unity4.6,Unity進(jìn)化到5.7,后面他們還會(huì)推出新的特性,我們希望結(jié)合一些Unity新特性,現(xiàn)在已經(jīng)有些游戲用5.6可以提升性能。不光是提升性能問題,Unity在多線程的渲染,也有很好的作用,使用引擎優(yōu)勢(shì)也是很必要的。
第四,隨著性能的提升,我們會(huì)對(duì)王者的畫質(zhì)進(jìn)行提升。
今天我的分享就到這里。
轉(zhuǎn)載于:https://blog.51cto.com/unitysky/1926609
總結(jié)
以上是生活随笔為你收集整理的腾讯邓君:《王者荣耀》翻过的同步技术相关的三座大山的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 干货 | OneAPM研发总监高海强:百
- 下一篇: MySQL 到PostgreSQL 的数