《炉石传说》架构设计赏析(2):Scene管理
今天我們主要分析一下爐石這款游戲中一共有哪些Scene,他們各自負(fù)責(zé)什么,以及它內(nèi)部的邏輯、UI的處理方式。
在正式開始之前,我來對前文中提到的Scene切換再做一些補(bǔ)充分析。前文中我們看到SceneMgr是調(diào)用了“Application.LoadLevelAdditiveAsync(this.sceneName);”,那內(nèi)存中的東西豈不是越搞越多嗎?我們再仔細(xì)看一下SceneMgr:SwitchMode()函數(shù),它是一個(gè)Coroutine,他主要進(jìn)行了下面這幾個(gè)步驟的操作:
1.調(diào)用當(dāng)前Scene的Scene:PreUnload()函數(shù);
發(fā)送FireScenePreUnloadEvent事件;
等待直到Unload過程走完(通過檢測LoadingScreen的階段);
2.調(diào)用Scene:Unload()函數(shù);
發(fā)送FireScenePreUnloadEvent事件;
調(diào)用成員函數(shù)PostUnloadCleanup()函數(shù),它調(diào)用了兩個(gè)關(guān)鍵的函數(shù):
- 首先是成員函數(shù):DestroyAllObjectsOnModeSwitch(),這個(gè)函數(shù)查找到所有的GameObject(Object.FindObjectsOfType(typeof(GameObject))),然后進(jìn)行了篩選(通過成員函數(shù)ShouldDestroyOnModeSwitch),除了一些全局對象之外(主要是SceneMgr、PegUI、Box、DefLoader),全都刪除了(通過調(diào)用Object.DestroyImmediate())。
- 然后調(diào)用了:Resources.UnloadUnusedAssets();
3.然后是調(diào)用前文提到過的成員函數(shù):LoadModeFromModeSwitch(),進(jìn)行了LoadLevelAdditiveAsync()操作;
綜上所述,爐石的Scene切換主要是包含兩步:1刪除所有非全局對象,卸載未引用的Asset;2加載新的Scene。(我倒是想到另外一個(gè)土鱉一點(diǎn)的替代方案:創(chuàng)建一個(gè)完全空的scene,調(diào)用LoadLevel加載它,那么所有沒有設(shè)置"DontDestroyOnLoad"的對象就都被刪除了。)
除了前文提到的Login,我們可以看到Scene還有很多派生類,詳見下圖:
?
這是我猜測的這些類和游戲內(nèi)容的對應(yīng)關(guān)系,賣二手游戲平臺(tái)沒有太仔細(xì)分析,可能有些對應(yīng)是錯(cuò)誤的:
下面我們就挑選一個(gè)簡單的Scene來分析一下它的內(nèi)部運(yùn)作機(jī)制,我們來看一下AdventureScene吧。Adventure相關(guān)的Class很多,我們只做一個(gè)粗略的分析,只涉及到下面這幾個(gè)類和接口:
?
首先我推測,在Hub屏幕中點(diǎn)擊中間的【Solo Adventure】(冒險(xiǎn)模式)按鈕之后,通過我們前文分析的LoadScene流程,加載了一個(gè)冒險(xiǎn)模式相關(guān)的Scene。它里面有一個(gè)GameObject綁定了“AdventureScene”這個(gè)腳本,我們可以看到AdventureScene:Awake()方法中主要是注冊了很多事件的回調(diào)。
我們可以看到有一個(gè)“AdventrueSubScenes”枚舉,它基本上對應(yīng)了下圖中的按鈕:
?
接下來還有一個(gè)"AdventureSubScene"是處理子場景對應(yīng)的一些邏輯的。
我們看到有“AdventureChooserTray”這個(gè)類:
1.我推測這個(gè)類就是用來處理上面這個(gè)游戲畫面的UI交互操作的;
2.這個(gè)類在Awake時(shí),通過調(diào)用“CreateAdventureChooserButton()”方法創(chuàng)建了上圖中的上部分那幾個(gè)冒險(xiǎn)游戲內(nèi)容模式相關(guān)的按鈕;
3.這些按鈕都綁定了事件回調(diào):AdventureChooserTray.ButtonModeSelected();當(dāng)這些按鈕被點(diǎn)擊時(shí),主要是調(diào)用:
?
- AdventureConfig:SetSelectedAdventureMode(),此函數(shù)修改內(nèi)部數(shù)據(jù)之后觸發(fā)事件:FireSelectedModeChangeEvent()
- AdventureChooserTray通過OnSelectedModeChange()響應(yīng)此事件,這也就是點(diǎn)擊上面那幾個(gè)按鈕之后要做的一些處理:包括更新左側(cè)的畫面、設(shè)置Choose按鈕狀態(tài)等等;
- 其中調(diào)用了PlayMakerFSM,主要是向其發(fā)送事件“Burst”;通過這里,我們可以確定爐石使用了PlayerMaker插件。
- AdventureScene也通過OnSelectedModeChanged()相應(yīng)了此事件;
4.它里面還有一個(gè)“PlayButton m_ChooseButton”成員變量,并把為它添加了EventListener,用來調(diào)用ChangeSubScene()方法。這就和游戲?qū)嶋H的操作對應(yīng)上來:在上面選擇模式,然后點(diǎn)擊下面的【Choose】按鈕,就進(jìn)行到下一步的選擇了。
5.AdventureChooserTray:ChangeSubScene()通過Coroutine的方式調(diào)用了AdventureConfig:ChangeSubSceneToSelectedAdventure(),然后調(diào)用了AdventureConfig:ChangeSubScene();它主要觸發(fā)兩個(gè)事件:
?
- FireSubSceneChangeEvent:AdventureScene通過OnSubSceneChange()函數(shù)響應(yīng)它,主要是調(diào)用AdventureScene:LoadSubScene(),內(nèi)部主要是調(diào)用AssetLoader.LoadUIScreen();
- FireAdventureModeChangeEvent:AdventureScene通過OnAdventureModeChanged()響應(yīng)它。
通過上面的分析,我們大致了解了上面這個(gè)游戲截圖中的操作實(shí)現(xiàn)邏輯。
這次的分析算是一次熱身,接下來重點(diǎn)分析有兩個(gè)方面:
?
- 游戲邏輯的組織,特別是技能的數(shù)據(jù)、邏輯組織;這可能需要經(jīng)過多次嘗試,慢慢接近;
- 游戲的Asset資源管理、加載機(jī)制;
OK,今天的分析就到這里,歡迎大家拍磚。后續(xù)分析敬請期待!
順便來秀一下我的魚人部隊(duì),別看這些1點(diǎn)學(xué)的小東西,加在一起還蠻歡樂的!
?
總結(jié)
以上是生活随笔為你收集整理的《炉石传说》架构设计赏析(2):Scene管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《炉石传说》架构设计赏析(3):Game
- 下一篇: 该如何在后期处理中,实现高亮描边的效果?