全面講解CocosCreator熱更新

前言

本文主要引用cocos關於熱更的官方文檔,並在此基礎上,總結sprout當前熱更流程。

什麼是熱更

熱更(新)本質上是從服務器下載需要的資源到本地,並且可以執行新的遊戲邏輯,讓新資源可以被遊戲所使用,它可以使開發者在不發佈新版本的情況下,修復 BUG 和發佈功能,讓開發者得以繞開蘋果的審核機制,避免長時間的審核等待以及多次被拒造成的成本。

Cocos 默認的熱更新機制並不是基於補丁包更新的機制,傳統的熱更新經常對多個版本之間分別生成補丁包,按順序下載補丁包並更新到最新版本。Cocos 的熱更新機制通過直接比較最新版本和本地版本的差異來生成差異列表並更新。

cocos熱更概述

manifest

瞭解cocos熱更之前,先要瞭解manifest。在cocos中,manifest是一種文件格式,其對應的文件簡稱資源描述文件,是用來描述本地或遠程包含的資源列表及資源版本。

manifest格式是仿照json格式,其關鍵字段的含義如下 :

{
    "packageUrl" :          遠程資源的本地緩存根路徑
    "remoteVersionUrl" :    [可選項] 遠程版本文件的路徑,用來判斷服務器端是否有新版本的資源
    "remoteManifestUrl" :   遠程資源 Manifest 文件的路徑,包含版本信息以及所有資源信息
    "version" :             資源的版本
    "engineVersion" :       引擎版本
    "assets" :              所有資源列表
        "key" :             資源的相對路徑(相對於資源根目錄)
        "md5" :             md5 值代表資源文件的版本信息
        "compressed" :      [可選項] 如果值為 true,文件被下載後會自動被解壓,目前僅支持 zip 壓縮格式
        "size" :            [可選項] 文件的字節尺寸,用於快速獲取進度信息
    "searchPaths" :         需要添加到 FileUtils 中的搜索路徑列表
}

Manifest 文件可以通過 Cocos Creator 熱更新范例中的 Version Generator腳本 來自動生成。

工程資源和遊戲包內資源的區別

大傢在創建一個 Cocos Creator 工程的時候,可以看到它的目錄下有 assets 目錄,裡面保存瞭你的場景、腳本、prefab 等,對應編輯器中的 assets 面板。但是這些工程資源並不等同於打包後的資源,在使用構建面板構建原生版本時,我們會在構建目錄下找到 res 和 src 文件夾,這兩個文件夾內保存的才是真正讓遊戲運行起來的遊戲包內資源。其中 src 包含所有腳本,res 包含所有資源。

所以我們的資源熱更新自然應該更新構建出來的資源,而不是工程的 assets 目錄。

在creator2.4.3中,重構瞭資源管理模塊,采用bundle模塊化管理資源。這裡分享一個通過uuid來獲取資源路徑的API

cc.assetmanager.utils.getUrlWithUuid  //轉換 uuid 為 url,這裡返回的url是運行時遊戲包內的資源路徑

searchPaths搜索路徑

在談到熱更之前,關於searchPaths的概念,有必要先瞭解一下。在大多數的時候,我們描述一個文件的路徑,都會基於一個”根目錄“去給到對應的”相對路徑“,並不會直接寫死成”絕對路徑“,這樣更利於維護、遷移。在遊戲開發中,其實我們”根目錄“也是很難保證其確定性、唯一性。就拿熱更功能而言,我們有一個圖片,假設其對應bundle目錄(默認是resources)的相對路徑是 ”./png/icon1.png“,當我們遊戲版本更新,需要更新該圖片的時候,由於包內的資源是不可寫的,那我們隻能讓其從另外一個地方讀取到新的圖片,為瞭保證代碼的一致性,如果我們可以改變其對應的”根目錄“,那代碼中之前的相對路徑都不需要修改,就能找到新的圖片。

在creator中,其維護勒一套搜索路徑的策略。對應的API可以查閱jsb.fileUtils.getSearchPaths、jsb.fileUtils.fullPathForFilename等。這裡簡述其原理。FileUtils中保存勒一個”根目錄“數組,index越低的優先級越高,在查找資源的時候,我們如果指定的是”相對路徑“,則其會按照searchPaths裡面的”根目錄“的優先級,去拼接成”絕對路徑“去查找資源,如果路徑有效,找到勒文件,則會停止繼續尋找。

在遊戲包的安裝目錄,肯定有一個目錄是存放我們打包後的各種腳本、資源,我們這裡稱之為”遊戲包目錄“,在熱更邏輯中,我們需要指定一個”熱更目錄“來存放我們熱更的內容,這兩個目錄都應該設為搜索路徑,並且需要控制版本,使優先級更高的目錄,對應的搜索路徑優先級也要越高,這樣,我們才能找到最新的文件。一般而言,”熱更目錄“的優先級需要高於”遊戲包目錄“。

cocos的基礎熱更流程

這是cocos官網資料的流程圖,註意,當前流程是用戶安裝好 app 後,第一次檢查到服務端的版本更新的情況,完整的熱更流程會更為復雜一些,後面我們再慢慢補充。

本文主要幫助大傢理解熱更本身的流程邏輯,其各個細節,如斷點續傳、下載進度、並發下載、錯誤檢測、解壓縮、錯誤恢復等細節問題,暫不討論。所以,把上訴流程圖,可簡單概況為:

根據當前包內的manifest的remoteVersionUrl字段,去下載其當前的版本描述文件,然後根據與本地的版本對比,若需要更新則更新到對應最新版本,不然就不需要更新,繼續後續流程。

這裡需要對其幾個關鍵點,再細化剖析一下:

_localManifest:當前包內的manifest

首先,”遊戲包目錄“內應該有一個默認的manifest文件,描述當前遊戲版本(”version”字段),這個manifest一般隨遊戲包卸載、安裝來更新。然後在”熱更目錄“也會有一個manifest文件,描述當前熱更目錄下的版本信息。我們每次啟動遊戲的時候都應該判斷一下,當前環境下,到底是”遊戲包目錄“,還是”熱更目錄“才是最新的版本,來調整其對應在searchPaths的優先級,較新的manifest也就稱為當前包內的manifest,代碼中用_localManifest來記錄。
註意,上述cocos基礎熱更流程中,並沒有這一步,是因為其表示流程是包第一次安裝的情況,熱更目錄下是沒有manifest文件,所以_localManifest就是”遊戲包目錄“,完整的熱更流程是需要做這一步判斷的。
上訴邏輯對應的代碼,請參閱:AssetsManagerEx的init、loadLocalManifest等函數。

先請求遠端版本manifest

在manifest的”remoteVersionUrl“字段中,其對應的是遠端服務器的版本文件,下面給到官方demo的一個version.manifest,便於大傢理解

{
    "packageUrl":"http://192.168.50.220:5555/tutorial-hot-update/remote-assets/",
    "remoteManifestUrl":"http://192.168.50.220:5555/tutorial-hot-update/remote-assets/project.manifest",
    "remoteVersionUrl":"http://192.168.50.220:5555/tutorial-hot-update/remote-assets/version.manifest",
    "version":"2.0"
}

從上面可以看到,version.manifest有一個“version”字段,這也是我們快速進行版本對比的依據。下載version.manifest,然後再與本地_localManifest的版本對比,來檢測當前包是否需要更新,這個過程代碼上一般命名為checkUpdate。

臨時文件夾的必要性

在熱更過程中,因為我們是多個資源依次下載的,這期間很可能出現各種問題,所有,我們需要一個臨時文件夾來暫存我們的下載,等到全部文件下載結束後,還需要檢測文件是否完整,才能去替換“熱更目錄”下的舊資源,不要直接在“熱更目錄”上下載,一旦出現問題,自己也搞不清那部分是新的,那部分是還是舊的。這種思路在程序設計中也可以借鑒體會,我們負責的一些數據、字段的維護,盡量能做到整體的替換更新,而不是到處隨意的去修改、賦值。

熱更是熱更差異化文件,是怎麼做到這點的

在manifest文件中,”assets”字段下,記錄每個資源的key和md5信息,隻需要遠端的_remoteManifest下記錄的資源進行對比,新的key則是新增資源,沒有的key則是需要刪除的資源,md5不同的就是需要更新的文件。
對應的代碼,請參閱:Manifest的genDiff等函數。

熱更好之後,怎麼讓其生效

當我們熱更好瞭新的資源後,怎麼在不需要調整代碼的情況下,讓其生效?哈哈,剛剛上文已經介紹過瞭,我們調整我們的searchPaths,讓“熱更目錄”優先級高於“遊戲包目錄”即可。
上面的流程圖中,cocos推薦的是用cc.sys.localStorage把_localManifest對應的路徑存儲起來,並在後續app啟動的開始階段,就從cc.sys.localStorage讀取對應路徑,設置到searchPaths中。
上訴方案固然可行,但是就一個完善的客戶端框架而言,尤其是針對多子項目的大廳類遊戲,個人認為這種動態存儲路徑、設置路徑並不是比較合適的方案。在架構設計上,我們需要先確定好整個客戶端的“熱更目錄”,並確定好優先級,即整個項目的searchPaths都是按照我們設定的邏輯固定好,而不是動態的去調整,這樣的好處是,在唯一的地方確定好searchPaths邏輯,之後僅需要根據邏輯,增刪對應路徑下的資源即可,這樣應該是更利於擴展和維護的。但同樣需要註意,這種固定好searchPaths的方案,在app安裝替換的時候,要維護好新的“遊戲包目錄”的版本與之前“熱更目錄”下的版本對比情況,如,app本地安裝升級後的版本比之前“熱更目錄”的版本更高,可以考慮把之前“熱更目錄”下的資源都清空掉,另外一種更麻煩的邏輯是,app安裝升級後的版本還是比“熱更目錄”版本低,這是要註意,“熱更目錄”存儲的是相對於升級前“遊戲包目錄”的差異化文件,升級後“遊戲包目錄”下的文件發生變化,那“熱更目錄”下的差異化文件就不一定能兼容當前的“遊戲包目錄”,這種情況也可以把“熱更目錄”情況,讓其重新去對比、熱更差異化文件。

舊的版本資源怎麼處理

cocos的熱更的雖然是差異化文件,但是其manifest腳本是記錄勒對應bundle所有的資源,我們是能知道哪些資源已經不需要的,上文genDiff函數也提到過,但是個人認為,舊資源的刪除需要謹慎,至少也是確保新資源更新好後,再去刪除舊資源。

總結

如果讀者在消化勒上訴的一些知識後,利用cocos提供的基礎功能函數,是完全可以徹底定制自己的熱更流程的。熱更,一言以蔽之,下載最新的遠端資源替換當前包體內的就資源而已。比如一些小項目,完全可以整包的下載、替換,可以忽略其中版本對比、searchPath調整、文件校驗等細節。

以上就是全面講解CocosCreator熱更新的詳細內容,更多關於CocosCreator熱更新的資料請關註WalkonNet其它相關文章!

推薦閱讀:

    None Found