主程/架構(gòu)師進(jìn)階 大師攻略

前言
今天的主題是《大型實時競技網(wǎng)游開發(fā)之:深入架構(gòu)與優(yōu)化》
為什么會有這個主題呢?因為很多同學(xué)在學(xué)習(xí)游戲開發(fā)的課程時或者碰到大型網(wǎng)絡(luò)游戲項目時,就會有這么幾個問題:
1,不知道如何制作一個大型的游戲項目
2,實時競技游戲的實時性如何表現(xiàn)
3,回合制或慢節(jié)奏的游戲里碰不到的問題會顯現(xiàn)出來
所以今天的課程就是幫助大家解決這些問題,會講解在開發(fā)大型實時競技網(wǎng)游時該如何做,如何優(yōu)化,這就是今天課程目標(biāo)!
版權(quán)聲明
本文為“優(yōu)夢創(chuàng)客”原創(chuàng)文章,您可以自由轉(zhuǎn)載,但必須加入完整的版權(quán)聲明
更多學(xué)習(xí)資源請加QQ:1517069595或WX:alice17173獲?。ㄆ髽I(yè)級性能優(yōu)化/熱更新/Shader特效/服務(wù)器/商業(yè)項目實戰(zhàn)/每周直播/一對一指導(dǎo))
點贊、關(guān)注、分享可免費(fèi)獲得配套學(xué)習(xí)資源
主題

今天的課程主題:
1,游戲開發(fā)可以分成幾個階段?
2,在什么階段做游戲的架構(gòu),在什么階段要針對游戲做優(yōu)化
3,幀同步游戲的架構(gòu)有哪些地方需要優(yōu)化?
4,代碼熱更新的優(yōu)化要點
5,資源熱更新的優(yōu)化要點
游戲開發(fā)的階段

游戲開發(fā)可以分成五個階段
第一階段:此階段需要確定需求(開發(fā)什么樣的游戲),進(jìn)行預(yù)研(確定項目能不能做),然后立項(籌備資金與人才)
第二階段:此階段需要開發(fā)底層庫和高層架構(gòu)
第三階段:開發(fā)業(yè)務(wù)邏輯
第四階段:進(jìn)行游戲測試
第五階段:里程碑達(dá)成(階段性目標(biāo)達(dá)成,進(jìn)入下一輪迭代)
注意點
1,沒有人能預(yù)見到所有的事情
2,在軟件開發(fā)里,唯一不變的是變換的需求
3,架構(gòu)不是空談
4,不管是在學(xué)習(xí)中還是在開發(fā)項目的過程中,都需要遵循商業(yè)項目的規(guī)律來做
《皇室戰(zhàn)爭》商業(yè)幀同步項目的開發(fā)過程

S1:項目原型開發(fā)
核心游戲系統(tǒng)
從零開始一步一步的實現(xiàn)游戲項目的核心系統(tǒng),比如《皇室戰(zhàn)爭》是卡牌實時競技游戲,那么它的特點就是:
1,離不開卡牌:需要開發(fā)卡牌系統(tǒng)
2,離不開卡牌的實時競技:需要有戰(zhàn)斗系統(tǒng)
基礎(chǔ)架構(gòu)支持:
一個商業(yè)項目需要有消息系統(tǒng)、UI框架、Shader效果、資源管理、代碼熱更新等架構(gòu)支持
大型分布式服務(wù)器開發(fā)基礎(chǔ)
S1里開發(fā)的主要是游戲客戶端部分,但現(xiàn)在不是網(wǎng)絡(luò)游戲的手機(jī)游戲可能很少了,而且單機(jī)游戲很難獲得良好的收益,所以要學(xué)習(xí)開發(fā)大型分布式服務(wù)器
有同學(xué)可能會問:“我在最早開發(fā)游戲時可能沒有考慮到網(wǎng)絡(luò)問題,那么我的項目架構(gòu)該怎樣支持網(wǎng)絡(luò)游戲開發(fā)呢?
在商業(yè)項目開發(fā)中,即使有一個功能現(xiàn)在暫時沒有做,也要把它的接口留好,該留哪些接口是由自己的開發(fā)經(jīng)驗所決定的
在大型分布式服務(wù)器開發(fā)階段里能學(xué)到:
分布式服務(wù)器
客戶端跟服務(wù)器的通信流程
怎么樣保證服務(wù)器的高性能
而且我們的服務(wù)器冗余非常小,當(dāng)你把服務(wù)器的協(xié)議定義好以后,架構(gòu)會直接幫你把服務(wù)器的數(shù)據(jù)庫、服務(wù)器跟客戶端通訊的協(xié)議生成好
S2:幀同步的客戶端和服務(wù)器架構(gòu)
什么叫幀同步呢?
傳統(tǒng)的網(wǎng)絡(luò)游戲,就是玩家發(fā)出一個操作到服務(wù)器,服務(wù)器接受到后會計算,然后傳遞給客戶端,比如把攻擊防御的結(jié)果返回給客戶端,如果是移動操作,就會發(fā)送移動后的角色坐標(biāo)給用戶的客戶端
但傳統(tǒng)方式在游戲過程中要傳輸?shù)臄?shù)據(jù)量是很大的,因為服務(wù)器向玩家客戶端傳遞的數(shù)據(jù)量就已經(jīng)很大了,還要把這些數(shù)據(jù)同步給其他客戶端
那該怎么辦呢?
可以采用幀同步,幀同步就是當(dāng)玩家執(zhí)行某一個操作后發(fā)給服務(wù)器時,服務(wù)器不會做運(yùn)算,會直接把這個消息廣播給所有客戶端
比如移動命令,玩家操作傳到服務(wù)器,服務(wù)器不會做運(yùn)算,而是直接把消息廣播給別的客戶端,它的通訊量只是你按了幾個鍵、按了什么鍵而已
《王者榮耀》就是采用幀同步來實現(xiàn)戰(zhàn)斗的,所以《王者榮耀》的實時性和打擊感做得很好。這是什么原理呢?
因為它把所有的運(yùn)算都放在游戲客戶端,這時服務(wù)器的性能瓶頸就只有它的數(shù)據(jù)傳輸能力和轉(zhuǎn)發(fā)能力
這是幀同步架構(gòu)服務(wù)器的能力要求,我們的項目需要能夠適應(yīng)這樣的服務(wù)器架構(gòu)
做完服務(wù)器架構(gòu)設(shè)計和功能實現(xiàn)以后,還需要機(jī)器人壓力測試,我們的服務(wù)器是能夠明確支持萬人同服的,這不是玩具代碼所能夠?qū)崿F(xiàn)的功能,而是一個真正的商業(yè)項目架構(gòu)
一個玩具項目就是寫完數(shù)據(jù)庫的協(xié)議、還要寫網(wǎng)絡(luò)協(xié)議、序列化協(xié)議、沒有數(shù)據(jù)緩存,也沒有實時競技的元素,那么這個項目的難度、對學(xué)習(xí)能力的鍛煉、通過實戰(zhàn)項目鍛煉的價值就沒有那么高
幀同步的難點在哪里呢?為什么說幀同步游戲是一個實時競技游戲呢?
我用《皇室戰(zhàn)爭》項目舉個例子:
我出了一張卡牌,在這張卡牌變成游戲單位行動時,它是由你來控制的嗎?不,它是由游戲的AI來控制技能釋放、進(jìn)行戰(zhàn)斗的
所以它的游戲AI系統(tǒng)會非常復(fù)雜,而且由于所有的運(yùn)算都是每一幀實時運(yùn)算的,你在開發(fā)那些慢節(jié)奏游戲時碰不到的問題都會在實時競技游戲里暴露出來,你在實時競技游戲中所得到的鍛煉跟傳統(tǒng)的回合制游戲也是不一樣的
而且?guī)接泻芏嚅_發(fā)要點,客戶端有很多坑點和可以對你形成經(jīng)驗的點,一些同學(xué)只是學(xué)習(xí)了S1加S2包括前面后面的一些基礎(chǔ)知識和后面的面試準(zhǔn)備,就能使面試官對他刮目相看
S3:雙端熱更新
前面的S1課程已經(jīng)實現(xiàn)了代碼熱更新,但S1中的代碼熱更只是在客戶端中進(jìn)行熱更,在S3里會再次深入代碼熱更新,學(xué)習(xí)客戶端熱更和服務(wù)器熱更
有同學(xué)可能會說:服務(wù)器要熱更新干什么?
如果你有一個大型的游戲項目,而這個項目經(jīng)常需要停服熱更的話,那這對游戲公司的運(yùn)營損失是很大的
而且當(dāng)出現(xiàn)一些小bug或者一些比較嚴(yán)重的bug時,當(dāng)前又暫時不能停服時,就可以實現(xiàn)服務(wù)器的實時熱更新來解決這個問題
當(dāng)然了,實時熱更新不是直接在生產(chǎn)服務(wù)器上更新,而是會先在開發(fā)服務(wù)器上測試,測試通過以后才會把它更新到支持熱更新的服務(wù)器上
客戶端熱更部分
ILRunTime能夠很好的支持客戶端的熱更新,并且不需要學(xué)另外一門編程語言
傳統(tǒng)熱更新是用Lua來做的,我們之前的課程也是用Lua來做熱更新,另外我們的Lua課程講的也是非常不錯的,我們從基本的使用到Lua在ToLua、XLua中使用、它的底層原理、性能瓶頸點、源碼實現(xiàn)、Lua跟C#的腳本綁定、GC的開銷、方方面面都對它做了系統(tǒng)的分析
不管是用ToLua、XLua、還是用ILRunTime,都需要對底層原理進(jìn)行學(xué)習(xí),如果不學(xué)習(xí)底層原理,那要怎樣理解它的優(yōu)化方式呢?怎樣把這個東西用好呢?
所以S3階段不是針對某一項技術(shù),而是要學(xué)習(xí)方法,理解它們的原理
S4:發(fā)現(xiàn)問題,解決問題,項目迭代
將學(xué)完S1課程后就能夠面試客戶端開發(fā);S1、S2學(xué)完能夠高薪入行;如果你是有經(jīng)驗的開發(fā)者,想要進(jìn)一步提升,那么建議將學(xué)完S2加S3,并且要對S2和S3的內(nèi)容有充分的理解
老師也會在筆試、面試模擬環(huán)節(jié)幫助大家進(jìn)一步鞏固知識,提升對知識的理解,當(dāng)然還有其他方式也能幫助大家理解知識,比如一對一指導(dǎo)和每周直播
S1到S3實際上就是從原型開發(fā)到項目架構(gòu)到具體功能實現(xiàn)的過程(也包括了項目的迭代),到S4以后就相當(dāng)于商業(yè)項目進(jìn)入了后期
在這個過程中可能會發(fā)現(xiàn)有各種各樣的問題,如果你平時只是做UI、做邏輯、接SDK,你可能發(fā)現(xiàn)不了這些問題,因為這些問題都是我們從規(guī)模、架構(gòu)、底層實現(xiàn)的角度提煉出的,我們也會教大家如何解決這些問題
架構(gòu)優(yōu)化

1,退出戰(zhàn)斗或游戲時報錯
這是很多同學(xué)在開發(fā)小型游戲時,想要退出戰(zhàn)斗或退出整個游戲項目時會出現(xiàn)的問題
如果你開發(fā)的是小游戲,那這個問題不會太明顯,因為游戲?qū)ο蟊容^少,要處理的數(shù)據(jù)量也少
但如果你的對象多一點,問題就會很明顯,這個問題是怎么造成的呢?
舉個例子:有A、B、C、3個GameObject,每個GameObject上都掛了相同類型的組件,每個組件上都有一個Start方法
那么你能告訴我這3個對象是哪個先Start,哪個后Start嗎?它可能第一次執(zhí)行時是A的Start,然后是B,最后是C;第二次啟動時可能是B先執(zhí)行,第三次可能是C先執(zhí)行
所以它們的順序是不確定的,那么再假設(shè)這三個對象之間有一些依賴關(guān)系,比如B中有一個X字段,A初始化的Start方法里有一個Y字段,它是X的平方
那如果現(xiàn)在程序的啟動順序是B先啟動,然后A再啟動,那么這沒有什么問題,但是如果反過來呢?是A先啟動,然后B再啟動,這樣Y就獲取不到有效X的值,程序就會報錯了
這是程序啟動時會碰到的問題,那么在退出時是不是也會遇到一樣的問題呢?答案是當(dāng)然的,想要解決這個問題就需要自己管理程序的生命周期
2,如何管理多次出現(xiàn)或數(shù)量較多的對象
舉個例子:
有一個角色實體,角色頭頂上有一個血條實體,角色身上還有一個掛件實體,血條有自己的屬性數(shù)值,掛件也有自己的屬性數(shù)值,那要怎樣管理角色實體,以及角色實體身上的血條和掛件呢?
從位置關(guān)系上來看這個實體:
血條要跟著實體走,所以它們是父子關(guān)系
從數(shù)據(jù)管理的角度上來看:
血條和掛件是角色實體的一部分
具體要怎么管理,大家可以自己想一想,把你們認(rèn)為對的答案發(fā)在評論區(qū)
3,異步性能太低,協(xié)程太分散,該如何管理
有些同學(xué)會在程序里大量使用協(xié)程或者異步,但不管是協(xié)程還是異步,都是由CLR框架管理的,并且不管是Lua,還是ILRunTime,它都是一種程序腳本
既然是腳本,那就是有腳本層調(diào)用開銷的,這就存在性能問題,那么這個性能問題該怎么解決呢?
很多時候我們使用異步主要就是兩個目的
1,延時
2,資源的異步加載
如果能解決這兩種異步產(chǎn)生的問題就可以取得更好的性能效果
另外還有一個問題就是:如果使用協(xié)程呢?
因為異步底層也是CLR通過協(xié)程來實現(xiàn)的,如果程序里過多的使用了異步或者協(xié)程,那么對CLR的管理開銷是比較大的
這就好比在程序中創(chuàng)建了很多的線程,線程的好處是可以一起干活,而多線程的壞處也正是它的好處帶來的,因為線程本身帶來的開銷就是很大的,線程調(diào)度帶來的開銷也是很大的
這就是架構(gòu)要優(yōu)化的點,它會出現(xiàn)難以管理的問題,而我們的項目已經(jīng)把這些問題都解決掉了,所以它跟你自己做著玩的項目是不一樣的
4,異步的流程管理
使用異步就會存在一個問題:異步程序會產(chǎn)生很多不能確定在什么時機(jī)執(zhí)行的程序流程
因為異步程序不是在這一幀就啟動的,它是在另外一幀或者另外很多幀以后才去執(zhí)行,而且是定時執(zhí)行的,不像同步程序,執(zhí)行順序很明確
所以異步不便于管理,但有時又不得不使用異步,這就存在一個問題:能不能在不需要用異步時把它同步化
這是要從程序的結(jié)構(gòu)上來做的優(yōu)化點,如果能實現(xiàn)會帶來很多好處
1,可以提高程序性能
2,可以讓程序更加穩(wěn)定
但有時可能不得不用到異步,這其實也是可以優(yōu)化的,比如下面的問題
5,卡牌”變兵“時的卡頓
這是我們在開發(fā)《皇室戰(zhàn)爭》時碰到的問題:
戰(zhàn)斗時的每個兵種、每種卡牌,在第一次放到場景中變成游戲單位時都會稍微卡一下
如果你是一個有經(jīng)驗的開發(fā)者,那你一定會碰到測試跟你說這樣的問題,而且這是一個非常高頻的面試考點,該怎么解決呢?
就是使用對象池,但因為對象池本身也是有使用開銷的,使用不當(dāng)就會在戰(zhàn)斗過程中造成更大的卡頓,因為對象池的原理是:
當(dāng)對象不夠時就會創(chuàng)建新對象
所以在戰(zhàn)斗時創(chuàng)建對象就會造成卡頓,這在我們的項目中有相應(yīng)的解決方案
6,對象池中的對象隨著戰(zhàn)斗單位的增多而膨脹
比如對象池里原本有五個對象,那當(dāng)這五個對象不夠用時有什么處理方法呢?
直接實例化一個新的對象,但它可能會卡頓,特別是戰(zhàn)斗的時候
那么應(yīng)該怎樣避免在戰(zhàn)斗時實例化造成卡頓呢?而且不停的實例化對象也會造成對象池的膨脹
比如一局戰(zhàn)斗中用到了50個對象,這些對象都是從對象池里取出來的,所以對象池里就必須要保證要有50個對象,也就是要實例化50個對象,那么在這局游戲進(jìn)行的過程中要增加對象或者這局游戲結(jié)束了,對象池里的對象不用了,該怎么辦呢?
這牽涉到了Mono的內(nèi)存管理問題,會在我們的課程里教給大家
7,對象池擴(kuò)容卡頓
8,UI模塊邏輯多了難以維護(hù)
如果你的UI很簡單,只有10行20行代碼,或者100行代碼,那就不用擔(dān)心這個問題
但如果有200或者300行代碼,甚至是四五百行代碼,那你就要注意怎樣解耦了
AA的優(yōu)化

1,如何最大化利用AA資源管理的優(yōu)勢
Addressable也是可以優(yōu)化的,先給大家介紹一下AA的能力:
使用AA可以在一小時以內(nèi)做完資源熱更新功能,傳統(tǒng)的AssetBundle方式是不可能達(dá)到這種效率的
因為僅僅只是AssetBundle的打包策略選擇、打包功能定制、打包工具編寫就得花一兩天,對于新手可能要一個禮拜,而且資源的釋放問題也需要自己處理
但AA只需要遵守AA的編程規(guī)范就不會犯錯,所以AA很簡單,但要把AA用好還需要對AA有更深入的理解,需要掌握AA的底層機(jī)制,包括面板上每一個選項的含義
2,AA能實現(xiàn)自動打包嗎?
3,AA能定制打包規(guī)則嗎?
要針對AA來實現(xiàn)打包規(guī)則定制需要對AA非常熟悉
4,AA資源冗余能否優(yōu)化
AA本身比AB(AssetBundle)好的地方就是它的功能拓展,可以通過功能擴(kuò)展來實現(xiàn)資源冗余的優(yōu)化
我們的框架對AA本身提出的資源冗余檢測和優(yōu)化方案做了進(jìn)一步的升級,成為了第二代的資源優(yōu)化方案
關(guān)于什么是資源冗余優(yōu)化,可以看我之前的關(guān)于資源熱更新的公開課
5,AA怎樣做到下載時全部更新完畢再進(jìn)游戲?如何顯示下載進(jìn)度?
AA默認(rèn)的方式就是資源隨用隨更新,比如角色模型發(fā)生了變化,那么當(dāng)游戲加載時,AA就會下載這個資源
但這種方式有個缺點:如果在戰(zhàn)斗時加載這個模型就會造成程序的卡頓
怎樣能做到下載時全部更新完再進(jìn)游戲呢?
這需要對Addressable的底層的API機(jī)制非常熟悉,并且要實現(xiàn)一套完整無錯的解決方案
這樣就可以下載全部資源再進(jìn)游戲,并且能顯示下載進(jìn)度
6,AA遠(yuǎn)程下載的緩存機(jī)制是是什么樣的
什么叫緩存機(jī)制?
當(dāng)遠(yuǎn)程下載的資源過多,不能一次下載完時,就要考慮到:如果資源在下載的過程中斷網(wǎng)、或者因為信號不好而下載中斷了,那么是要重新把資源下載一次嗎?AA會重新下載資源嗎?如果要重新下載資源,那怎樣最小化資源的下載量呢?這都是商業(yè)游戲項目需要考慮的
7,如何打包才能達(dá)到資源更新的最小開銷,并且能夠合理的驗證資源的版本是否更新?
需要理解一些AA的打包優(yōu)化策略
ILRunTime優(yōu)化

1,游戲戰(zhàn)斗過程中,游戲單位增多時GC開銷比較大,CPU運(yùn)行卡頓
這個問題無關(guān)使用ILRunTime還是用ToLua,它們都會有這個問題
另外ILRunTime在性能調(diào)試方面比ToLua、XLua方便的多,為什么?
因為ILRunTime的底層就是C#,所以可以直接通過Unity的性能圖表Profiler看到它的內(nèi)存、垃圾的開銷
內(nèi)存垃圾除了占用內(nèi)存以外還會造成CPU的卡頓,如何優(yōu)化?
這個問題的關(guān)鍵在于你能不能讀懂它的性能圖表、知不知道性能圖表產(chǎn)生問題的原因在哪里、如何優(yōu)化、和優(yōu)化時有哪幾種方法
2,ILRunTime的性能如何最大化
有同學(xué)會問:ILRunTime跟Lua的性能比究竟怎么樣?
ILRUnTime不比Lua差,甚至在某些方面的性能是遠(yuǎn)遠(yuǎn)超過基于Lua的解決方案的,不管是ToLua還是XLua
至于為什么?和如何實現(xiàn)?可以參考我們的VIP課程
小結(jié)

游戲開發(fā)的階段
在什么階段要做架構(gòu)
幀同步的優(yōu)化要點
代碼熱更新的優(yōu)化要點
資源熱更新的優(yōu)化要點
進(jìn)一步學(xué)習(xí)的內(nèi)容

希望大家在平時多思考一些技術(shù)問題,如果你想系統(tǒng)學(xué)習(xí)這里的每一個解決方案,可以考慮參加我們的課程
我想強(qiáng)調(diào)一點就是:做比說更重要,剛才也提到了一些問題的解決方案,但如果不親自做一遍,是不會清楚里面的坑點的,也不能深入理解它,形成深刻印象,所以實踐才是學(xué)習(xí)的要義所在
寫在最后
更多學(xué)習(xí)資源請加QQ:1517069595或WX:alice17173獲?。ㄆ髽I(yè)級性能優(yōu)化/熱更新/Shader特效/服務(wù)器/商業(yè)項目實戰(zhàn)/每周直播/一對一指導(dǎo))
點贊、關(guān)注、分享可免費(fèi)獲得配套學(xué)習(xí)資源