王者榮耀爲什麼選擇幀同步和Unity引擎

原文鏈接:http://king.shandian.biz/88.html

Unity的選擇優勢:

1.易上手,我們花三週就可以做出Demo,可以看到易上手是它的一個非常大的優勢。

2.它的工具都是很完善的,能夠做到一站式解決,你不需要在這裏面下載工具,那裏面額外補充一些插件。

3.它插件資源很豐富,我們從最開始做Demo的時候,基本上都可以從Asset Store中找到一些可以用來驗證我們想法的資源,可以加快我們開發的效率。

4.上面這三點加起來,就能體現出它非常明顯的優勢,即開發效率特別高。

5.它還有跨平臺的優勢,它本就是跨平臺的引擎。

6.最後它還能讓你更方便地補充技術人員,社招也很容易招聘到熟悉Unity的開發人員。

狀態同步的優點:

第一,它的安全性非常高,外掛基本上沒有什麼能力從中收益。

第二,狀態同步對於網絡的帶寬和抖動包有更強的適應能力,即便出現了200、300的輸入延遲再恢復正常,玩家其實也感受不到不太舒服的地方。

第三,在開發遊戲過程中,它的斷線重連比較快,如果我的遊戲崩潰了,客戶端重啓之後只需要服務器把所有重要對象的狀態再同步一次過來,重新再創建出來就可以了。

第四,它的客戶端性能優化優勢也比較明顯,比如優化時可以做裁剪,玩家看不到的角色可以不用創建,不用對它進行運算,節省消耗。

狀態同步的缺點。

第一,它的開發效率相對幀同步而言要差一些,很多時候你需要保證服務器與客戶端的每一個角色對象的狀態之間保持一致,但事實上你很難做到一致。

比如客戶端和服務器端更新的頻率,對優化的一些裁剪,網絡的抖動等等,你要讓每一個狀態在客戶端同步是比較難的,而你要想調試這些東西,來優化它帶來的漏洞、不一致的現象,花費的週期也會比較長,想要達到優化好的水平也比較難。

第二,它比較難做出動作類遊戲打擊感和精確性。比如說你要做一個射擊類角色,他的子彈每秒鐘要產生幾十顆,基於狀態同步來做是比較難的,因爲系統在很短時間內,會產生很多數據,要通過創建、銷燬、位置運算來同步。

第三,它的流量會隨着遊戲的複雜度,而逐漸增長,比如角色的多少。我們做《王者榮耀》時,希望在3G、4G的網絡條件下也能夠玩PvP,所以要對流量的消耗能控制在比較合理的水平,不能打一局遊戲就消耗幾十兆的數據流量。

幀同步的優點:

(這種技術應用的很廣泛,最早的《星際爭霸》《魔獸爭霸3》都採用了幀同步,他們都基於局域網運行,網絡的條件非常好,也不需要服務器就能搞定。)
第一,它的開發效率比較高。如果你開發思路的整體框架是驗證可行的,如果你把它的缺點解決了,那麼你的開發思路完全就跟寫單機一樣,你只需要遵從這樣的思路,儘量保證性能,程序該怎麼寫就怎麼寫。

比如我們以前要在狀態同步下面做一個複雜的技能,有很多段位的技能,可能要開發好幾天,纔能有一個稍微過得去的結果,而在幀同步下面,英雄做多段位技能很可能半天就搞定了。

第二,它能實現更強的打擊感,打擊感強除了我們說的各種反饋、特效、音效外,還有它的準確性。利用幀同步,遊戲裏面看到這些揮舞的動作,就能做到在比較準確的時刻產生反饋,以及動作本身的密度也可以做到很高的頻率,這在狀態同步下是比較難做的。

第三,它的流量消耗是穩定的。大家應該看過《星級爭霸》的錄像,它只有幾百K的大小,這裏面只有驅動遊戲的輸入序列。幀同步只會隨着玩家數量的增多,流量纔會增長,如果玩家數量固定的話,不管你的遊戲有多複雜,你的角色有多少,流量消耗基本上都是穩定的。這點延伸開來還有一個好處,就是可以更方便地實現觀戰,錄像的存儲、回放,以及基於錄像文件的後續處理。

幀同步的缺點:

第一,最致命的缺點是網絡要求比較高,幀同步是鎖幀的,如果有網絡的抖動,一段時間調用次數不穩定,網絡命令的延遲就會擠壓,引起卡頓。

第二,它的反外掛能力很弱,幀同步的邏輯都在客戶端裏面,你可以比較容易的修改它。但爲什麼《王者榮耀》敢用幀同步,一方面是因爲當時立項的時候開發週期很短,半年時間要做上線,要有幾十個英雄,存在時間的壓力,另一方面,MOBA類遊戲不像數值成長類的遊戲,它的玩法是基於單局的,單局的作弊修改,頂多影響這一局的勝負,不會存檔,不會出現刷多少錢刷多少好的裝備的問題,而且作弊之後我們也很容易監測到,並給予應有的懲罰,所以我們認爲這不是致命的缺點。

第三,它的斷線重回時間很長,相信臺下也有很多王者玩家,也曾碰到過閃退以後重回加載非常長的情況,甚至加載完以後遊戲也快結束了,這是幀同步比較致命的問題。

第四,它的邏輯性能優化有很大的壓力。大家應該沒有見到哪一款大型遊戲是用幀同步來做的,因爲這些遊戲的每一個邏輯對象都是需要在客戶端進行運算的。如果你做一個主城,主城裏面有上千人,上千人雖然玩家看不到它,但遊戲仍然需要對他們進行有效的邏輯運算,所以幀同步無法做非常多的對象都需要更新的遊戲場景。

(如果要做有趣的英雄,有趣的技能,它在狀態同步上面很難調出一個比較滿意的效果。)

幀同步的技術原理相當簡單,10、20年前在應用這種技術了,從一個相同初始的狀態開始,獲得一個相同的輸入,往下一幀一幀執行,執行時所有代碼的流程走得都是一樣的,這個結果調用完了以後,又有一個新狀態,完成循環。相同的狀態,相同的流程,不停的這樣循環下去。

這個原理雖然簡單,但是你要去實現它的時候,還是會有很多坑。

右邊寫的是實現要點,這是我們在解決第一座大山經驗的總結,也是我們實際開發過程當中做的事情。

首先,我們所有的運算都是基於整數,沒有浮點數。浮點數是用分子分母表達的。

其次,我們還會用到第三方的組件,幀組件也要需要進行一個比較嚴格的甄別。我們本身用的公司裏面關於時間軸的編輯器裏面,最初也是是浮點數,我們都是進行重寫改造的。

再次,很多人初次接觸幀同步裏面的問題,就是在寫邏輯的時候和本地進行了關聯、和“我”相關,這樣就導致不同客戶端走到了不同的分支。實際上,真正客戶端跟邏輯的話,要跟我這樣一個概念無關。

接下來還有隨機數,這個要嚴格一致。這是實現的要點,嚴格按照這上面的規則寫代碼還是有可能不同步,本身就很難杜絕這樣的問題。

最後,真正重要的是開發者要提升自己發現不同步問題的能力,什麼時候不同步了,不同步你還要知道不同步在什麼點,這是最關鍵的。你需要通過你的經驗和總結提升這樣的能力。這個能力還是通過輸出來看不同客戶端不同輸出,找到發生在什麼點。

比如在《王者榮耀》裏,我們看到不同步的現象應該是這樣,有人對着牆跑,你看到的和別人玩的遊戲是不一樣的,就像進入平行世界。

最開始測試《王者榮耀》的,我們希望不同步率達到1%,就是100局裏面有1局出現不同步,我們就算遊戲合格,但實際上對於這麼大體量遊戲來說,這個比率是有問題的,經過我們不停的努力,現在已經控制在萬分之幾,一萬局遊戲裏面,可能有幾局是不同步的。

這個問題不一定是代碼原因或者沒有遵循這些要點纔出現的,有可能是你去修改內存,你去加載資源的時候,本地資源有損害或者缺失,或者是異常。說白了,你沒有辦法往下執行,大家走了不同分支,這都可能引起最終是不同步的。

如果你不同步概率比較低,到了這種萬分之幾概率的時候,很難通過測試來去還原,去找到這樣不同步的點。

最開始我們遊戲出現不同步的時候,就是在週末玩家開黑多的時候,隨着你的概率越來越低,基本上你就自己就還原不出這些問題了,只能依靠玩家幫你還原這樣的場景,來分析這樣的不同步問題。

同步性遵循這樣的要點,按照這樣的思路來寫,加上你不同步定位的能力,有了監控手段能夠去發現,這個問題其實就解決了。解決之後,你就可以好好享受幀同步的開發優勢。

第二座大山就是網絡,《王者榮耀》技術測試版本出臺的時候,延遲非常大,而且還是卡頓,現在看一下幀同步裏面比較特別的地方。幀同步有點像在看電影,它傳統的幀同步需要有buffer,每個玩家輸入會轉發給所有客戶端,互相會有編號,按順序輸入幀。

比如我現在已經收到第N幀,只有當我收到第N+1幀的時候,第N這一幀我纔可以執行。服務器會按照一定的頻率,不同的給大家同步幀編號,包括這一幀的輸入帶給客戶端,如果帶一幀給你的數據你拿到之後就執行,下一幀數據沒來就不能執行,它的結果就是卡頓。

網絡絕對理想的情況下還好,但現實的網絡環境不是這樣的。幀同步要解決問題就是調試buffer,以前有動態的buffer,它有1到n這樣的緩衝區,根據網絡抖動的情況,收入然後放到隊列裏面。

這個buffer的大小,會影響到延遲和卡頓。如果你的buffer越小,你的延遲就越低,你拿到以後你不需要緩衝等待,馬上就可以執行。但是如果下一幀沒來,buffer很小,你就不能執行,最終導致的結果你的延遲還好,但是卡頓很明顯。

如果調到幀同步的buffer,假如我們認爲網絡延遲是1秒,你抖動調到1秒,那得到的結果雖然你畫面不抖動了,但是你的延遲極其高。如果連最壞的網絡情況都考慮進去,buffer足夠大,那麼記過就跟看視頻是一樣的,平行的東西,看你調大條小。一些局部的措施我們都做過,都是一樣的問題。

具體我們怎麼優化卡頓的問題呢?

剛纔提到該幀同步與buffer,這個buffer可以是1也可以到n,我們要解決我們的延遲問題,我們就讓buffer足夠小。事實上《王者榮耀》最後做到的buffer是零,它不需要buffer,服務器給了我n,馬上知道是n,我收到n,我知道下一次肯定是n+1,所以我收到n之後馬上就把n這一幀的輸入執行了。

那麼爲什麼不卡頓了,畫面不抖動了?

最後一個關鍵點,是本地插值平滑加邏輯與表現分離。客戶端只負責一些模型、動畫、它的位置,它會根據綁定的邏輯對象狀態、速度、方向來進行一個插值,這樣可以做到我們的邏輯幀率和渲染幀率不一樣,但是做了插值平滑和邏輯表現分離,畫面不抖了,延遲感也是很好的。

做了這些後,我們還把TCP換成UDP,在手機環境下,弱網的情況下,TCP很難恢復重連,所以最後用了UDP來做。整體來說,在網絡好的情況下,它延遲也是很好的,在網絡比較差的情況下做插值,也是傳統CS的表現。

我們經常見到角色A和B,有些客戶端A在左B在右,有些是A在右B在左,幀同步邏輯上面AB之間的距離和座標都是完全一樣,但是畫面上看到他們可能會不重合,那就是你把它們分離之後的表現。網絡極其好的情況下,它應該是重合的,但是在網絡差的情況下,可能會有些偏差。這裏面是最重要的一塊優化。

第三座大山,是我們對性能的優化。

本身幀同步邏輯上面在優化上面存在一些缺點,所有的角色都需要進行運算。這方面我們也是藉助Unity的特性,如果你想追求性能上的極致,有些東西你需要尋求好的方式。

第一點是熱點的處理。

我們是不用反射的,它都有GC性能開銷,我們的做法裏面,會把對象的顯示隱藏放在不同的渲染層裏面,儘量讓整個遊戲幀率是平滑的過程。還有我們本身有自己的系統,比如AI,在《王者榮耀》這樣的多角色遊戲中,你如果想要做出比較好的體驗,那麼AI就要做得比較複雜。

而要去優化熱點,我覺得就只有這三個步驟可以走。

首先,從程序的結構上面能找到更優的,它的優化效果就是最明顯的;其次,如果你的結構都是用的最好,就去挖掘局部的算法,調整你代碼的一些寫法。最後,如果局部的算法都已經調到最優還是沒有什麼辦法,那只有一條路,就是犧牲整個質量,就是分幀降頻。

第二點是GC,這塊剛纔說不用反射,還有裝箱和拆箱的行爲也是儘量少用。

Unity指導過我們的優化,從GC上面的考慮,他們建議每一幀應該在200個字節以內是比較好的狀態,其實很難做到,王者也是每一幀在1k左右,很難做到200。

第三點是Drawcall,這些傳統的優化手段大家都用的很熟了。

第四點是裁剪,幀同步裏面是不能裁剪的,表現裏面我看不到的可以降低頻率或者不更新它,這在表現裏面可以做的。

第五點是3DUI的優化,比如《王者榮耀》的血條、小地圖上面疊的元素等等,這些UI都比較豐富,這塊我們用了31UI的方式來優化,沒有用UGUI裏面進行血條方面的處理。

我們也犧牲了一些東西,我們把所有東西都加載了,在遊戲過程當中,我們希望不要有任何IO行爲,包括輸出我們都是要佈局的。你處理的決策和複雜度,如果在一幀裏面放出100顆子彈,在放100顆子彈的時候一定要掉幀的,一定要在力所能及的時候把這些東西做到極致。

上面提的是我們的第一代,也是在去年5月份以前做的優化方案。5月份以後,我們還做了另外一件事情:GameCore。

首先,爲什麼我們覺得iOS比安卓的優化效率高一些,一方面是iOS的CPU架構包括系統確實都優化的比較好,另一方面我們用的Unity4.6,在IOS下面它本身效率高一些,在安卓端的機器各種各樣,性能也是千差萬別,我們只能用性能比較差的方式。

因爲我們已經做到邏輯和表現的分離,那麼我們能不能把邏輯獨立出來,做成一個C++的東西,實際上我們在去年開始已經在這樣做了。做之前也測試過C++和Mono性能的差別,大概是2.5左右,本身我們的邏輯佔比遊戲消耗20%多,邏輯不是一個大頭,我們做了這件事情之後,還是有效的,幀率提升了2到3幀,花的時間很長。

其次,做GameCore以後最明顯的變化是我們以前邏輯上的GC沒有了,我們有自己內存的管理、對象的管理,包括裏面所有的容器類這些東西都是我們自己實現的,包括反射整個一套。它有了自己的內存管理,本身的效率就會比較高,這就已經是一個比較明顯的優勢了。

再次,有了GameCore之後,又多了很多應用場景,這個東西就是玩法的服務器版本,應用場景運行服務器要做很多的分析,還有第三方使用都是可以的。

最後,GameCore還有可以擴展多線程的潛力。

今後,我們也有幾個計劃。

第一,我們考慮能不能在熱更新上面有所突破。因爲王者這樣一個遊戲類型,包括它的體量,我們對於性能有一個比較極致的追求,不會輕易使用腳本層面在性能層面本身就不是最好的。這個我們要去研究的就是熱更新,性能最好的方式。

第二,我們也在和硬件廠商溝通,他們希望遊戲能夠真正發揮多核性能上的優勢,大部分的遊戲在單核上面,把一個核吃的滿滿的,很多時候我們現在得出的結論,GPU性能也很強,王者並沒有對GPU佔滿,可能只用了30%,CPU反而吃的比較滿,吃滿以後它還有另外一個壞處,它的發熱、降頻,你如果用多線程、多核去儘量平坦,讓它不要處於高頻的工作方式,反而會有更好的效果。

第三,我們現在用的是Unity 4.6版本,但Unity已經進化到5.7版了,後面他們還會推出新的特性,我們希望結合一些Unity新特性,現在已經有些遊戲用5.6可以提升性能。

最後,不光是提升性能問題,Unity在多線程的渲染,也有很好的作用,使用引擎優勢也是很必要的。隨着性能的提升,我們會對王者的畫質進行升級。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章