實作遊戲 App 的熱更新功能

hot-fix-mechanism

寫遊戲這麼久,第一次在遊戲 App 上實作「熱更新」功能。

所謂熱更新,我想大致上可分成兩個層次:

  1. 僅下載圖片、音源等素材檔案,藉由設定檔等方式,無需更新程式碼即可使用新素材檔。目的在於大幅縮減初始 app bundle 的檔案尺寸,使玩家更快更容易下載遊戲。
  2. 除了下載素材檔案以外,亦須下載程式邏輯檔案,目的在於繞過 App Store 審查。正所謂「有 Bug 堪修直須修,莫待 Apple 審核過」,以前的經驗是,經常修好了要命臭蟲後,等待審核過卻是等到「花兒也謝了」,玩家也跑光了。修臭蟲的時效性是關鍵所在。

以工程師的觀點來看,可將「熱更新」功能分解為下列幾個步驟:

  1. 實現 HTTP 下載檔案功能
  2. 檢查本地端與伺服器端的檔案版號
  3. 依下載進度呈現進度條與數字
  4. 程式碼檔案須能區分 32/64 bits
  5. 程式碼與素材檔,支援多重讀檔路徑
  6. 下載完畢後,重新載入圖片等素材檔案
  7. 下載完畢後,重新載入程式碼(Lua 限定)
  8. 檢查檔案正確性,並更新本地端版號

以下詳述各步驟的做法。

1. 實現 HTTP 下載檔案功能

在 iOS 平台上,可用第三方函式庫 AFNetworking 實現下載功能。至於 Android 平台,則可使用官方 SDK 提供的 DownloadManager 實作。

小提示:我原先試著使用 luasocket 來做 http 檔案下載,結果嘗試許久後,才發現 luasocket 並不支援 HTTPS 協定下的檔案下載。若把檔案放在 dropbox 或其他使用 HTTPS 的網路空間上,就會無法正確取得檔案。

2. 檢查本地端與伺服器端的檔案版號

首先下載 patch header 檔案,內容記載此 patch 的版號,以及必須更新的程式碼與素材檔案列表。在下載 patch header 完成後,先檢查 App 版號是否小於 patch header 版號。若否則進入遊戲,若是就進入下載檔案的程序。

3. 依下載進度呈現進度條與數字

簡易版:依「檔案數量」做概略顯示,例如:下載進度 33%(33/100 )

進階版:依「檔案尺寸」做精確顯示。例如:下載進度 33.1415926%(33,100 / 100,000 KB)

4. 程式碼檔案須能區分 32/64 bits

目前 Android 無此需求。而在 iOS 上可用 preprocessor macro 來確認是否為 arm64 裝置,然後再依此下載正確的程式碼版本:

bool IsArm64Device()
{
#if __LP64__
    return true;
#else
    return false;
#endif
}

5. 程式碼與素材檔,支援多重讀檔路徑

在載入程式腳本、圖片、聲音或其他資源檔之前,先檢查此檔案是否存在於 app 的文件下載目錄中,若有則使用之,若無則使用 app bundle 中原本包進去的資源檔。

6. 下載完畢後,重新載入圖片等素材檔案

在這個步驟中,一般需要先卸載所有的 texture 資源,並且毀滅在遊戲初始化時建立的相關資源物件,確認不會造成 memory leak。

7. 下載完畢後,重新載入程式碼

熱更新功能的所有步驟中,實作上最困難的應該就是這一步了。

所幸「有 Lua,沒懦夫」,如果你的遊戲 App 和我一樣,大部分是由 Lua 所撰寫而成的,那麼只要充分利用 Lua 的特性,依照原先順序重新載入 lua scripts,便可即時覆寫正在運作中的程式碼。輕鬆搞定,打完收工。

8. 檢查檔案正確性,並更新本地端版號

使用 CRC 或其他的檔案驗證做法,檢查下載檔案的正確性。將新版號儲存於 app 的本地端資訊中。

相關進階功能

在完成基礎的熱更新功能後,便可更進一步完成以下進階功能:

  1. 區分「第一包」和「後續更新包」的內容。
  2. 利用此機制做簡易的停機公告。
  3. 可限制最小 app bundle 版本。在下載更新前先做檢查,若玩家小於此版本,則強制前往商店更新 App。
  4. 若在下載過程中網路中斷,重新嘗試連線後可恢復上次的下載進度,而不需要從頭開始。
  5. 下載檔案時,讓玩家可以做別的事,例如:觀看遊戲提示、進行小遊戲。

 

熱更新功能完成後,便可將遊戲素材檔案切分開,使 App 於合適時機點下載對應素材。不要再做那種「第一次開遊戲就先載個幾百 MB 資料」 的事了,連教學都沒完成的玩家,無須浪費珍貴的網路頻寬在他身上,玩家也不會落入「才剛下載遊戲,一開又得等下載」的窘境,或是像我一樣:「要先下載檔案啊,我還是回家有空再開好了。」讓本來想玩遊戲的興致都沒了。

以上,「熱更新」功能已實現在新遊戲 App 上。未來若有訂正或進階的做法,會持續更新在這篇文章裡。

Leave a Reply