《炉石传说》架构设计赏析(1):游戏启动流程
今年的Unity Awards兩項大獎頒給了暴雪的《爐石傳說》,這真是對Unity一個再好不過的宣傳了——你看,暴雪都開始用Unity了。大家都知道,目前Unity發布的游戲大多都沒有對程序集進行混淆、加密,所以作為一個爐石的玩家&Unity的初學者,自然不能錯過這個機會。讓我們好好看一下暴雪的代碼吧。爐石傳說的游戲內容的非常豐富多彩,所以我花了一些時間分析了其程序集,將一些設計思路記錄下來,與大家分析。
做這些分析的主要目的是:
1.看看爐石如何組織游戲邏輯,以支撐復雜的技能邏輯、表現等;
2.看看爐石是如何使用Unity的,其結構設計和技巧上有什么值得學習的地方;
3.向暴雪的程序員好好學習一下英語。
下面我們就正式開始。我習慣先分析一下游戲的啟動流程,這中間就涉及到了游戲基礎數據的管理&初始化,各種管理器級別的類,以及相互引用關系也會初步顯現。
首先看一下我找到的一些游戲啟動過程相關的類,下面是他們的類圖:
?
接下來我們分析一下游戲啟動的操作流程。
?
- ApplicationMgr對象應該綁定到了一個場景對象中,這個場景應該在游戲啟動中加載;
- ApplicationMgr:Awake()被Unity引擎自動調用;
- 調用ApplicationMgr:Initialize(),在這個函數中順序調用了以下成員函數來進行初始化:
- InitializeMode():設置模式為ApplicationMode.PUBLIC;
- InitializeUnity():設置了UnityEngine.Application的一些屬性;
- InitializeGame():看來核心的內容在這里,初始化Network,GameMgr等;
- InitializeWindowTitle();
- InitializeOptionValues();
游戲啟動應該不只這點東西。由于我們純靠程序集的動態分析,無法知道它的場景編輯、對象的腳本綁定,也不能跟蹤調試,所以只能靠猜測了。另外,一些事件是通過網絡消息觸發的,這也給靜態分析帶來了一些難度。
OK,我們繼續。我注意到了class Login,它從Scene派生。查看了一下Scene的派生類還有不少,我猜測每個派生類,作為特定Scene邏輯處理的腳本。而Login應該是在第0個場景中被激活運行。我們看一下Login:Start(),這屬于MonoBehavior自動調用,他主要做了這樣幾件事:
?
- 注冊了一些資源版本檢測、Login相關的網絡消息回調;
- 通知SceneMgr場景加載完成;
- 調用成員函數:AutoLogin();此函數調用Network.AutoLogin();
從配置文件中找到User Name,然后調用ConnectAPI.AutoLogin()——奇怪的是發現這個函數只是簡單的返回false,并沒有進行實際的操作。
我們在來看一下Login:Update(),這個也是屬于被自動調用的腳本函數。在這里它檢測了Login的狀態,并調用了成員函數LoginOk(),而它有主要調用了AssetsVersionCheckCompleted(),這個函數內容很豐富:
?
- 通知其他模塊,已經登錄成功,包括:BaseUI、InactivePlayerKicker、HealthyGamingMgr、GameMgr;
- 調用一些模塊的Initialize函數,包括:DefLoader、CollectionManager、AdventureProgressMgr、Tournament、StoreManager等;
我們前面看到了Login從Scene派生,并且還有一個SceneMgr類。我們可以斷定游戲根據不同的邏輯劃分成了一些scene,接下來我們就探索一下Scene切換的流程。還是從Login入手。
以下流程都是在Login類中完成,下面描述的過程都是Login成員函數的調用:
?
- 首先我找到了Login:OnNetCacheReadyStep2()函數,這個應該是login流程中某一步的網絡消息回調函數;
- 它會調用WaitForAchievesThenInit()這個Coroutine函數,這個函數檢測了是否需要播放視頻,然后調用ReconnectOrChangeMode();
- 此函數處理重新連接,一般的話應該是調用了ChangMode();
- ChangMode()處理了新手教程相關的啟動邏輯,一般的話會調用ChangeMode_Hub();
- 這個地方貌似是調用了一個技能特效,特效播放完成之后調用回調函數:OnStartupHubSpellFinished();
- 此函數調用ShowUnAckedRewardsAndQuests();
- 這里面主要是調用了HandleUnAckedRewardsAndCompletedQuests(),哦~,這應該是游戲啟動的時候顯示當前任務還有未領取的獎勵的那個界面;
- 它會調用ShowNextUnAckedRewardOrCompletedQuest();
- 其中主要調用了ShowWelcomeQuests();
- 當幸虧顯示的任務為0時,則調用了這一句:SceneMgr.Get().SetNextMode(SceneMgr.Mode.HUB),這是關鍵的一步了;
接下來就我們跳轉到SceneMgr類中,二手游戲出售繼續探索Scene切換流程的實現。以下都是指的SceneMgr的成員函數:
- SetNextMode()函數主要就是把“m_nextMode”成員變量設置為了指定值;
- 接下來看一下Update(),這個函數主要是檢測了是否需要切換Mode,然后調用了:
SwitchMode():這個是一個Coroutine,它主要是調用了LoadModeFromModeSwitch(),它的核心也是調用LoadMode();
直接調用LoadMode()
?
- LoadMode()函數,主要是根據當前的Mode,調用LoadScene();
- LoadScene()函數主要是調用了:Application.LoadLevelAdditiveAsync(this.sceneName);
這樣就完成了場景的切換。
OK。通過以上分析,我們大體了解了游戲啟動過程是這樣的:
進行賬戶驗證;
賬戶驗證完畢之后,顯示未領取的獎勵和任務;
然后切換到SceneMgr.Mode.HUB模式,即加載了相應的Scene。
關于游戲啟動的分析告一段落,下一篇將會分析一下爐石的Scene組織。
總結
以上是生活随笔為你收集整理的《炉石传说》架构设计赏析(1):游戏启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 该如何在后期处理中,实现高亮描边的效果?
- 下一篇: 当人工智能遇到游戏