前言
本文主要引用cocos關(guān)于熱更的官方文檔,并在此基礎(chǔ)上,總結(jié)sprout當(dāng)前熱更流程。
什么是熱更
熱更(新)本質(zhì)上是從服務(wù)器下載需要的資源到本地,并且可以執(zhí)行新的游戲邏輯,讓新資源可以被游戲所使用,它可以使開(kāi)發(fā)者在不發(fā)布新版本的情況下,修復(fù) BUG 和發(fā)布功能,讓開(kāi)發(fā)者得以繞開(kāi)蘋(píng)果的審核機(jī)制,避免長(zhǎng)時(shí)間的審核等待以及多次被拒造成的成本。
Cocos 默認(rèn)的熱更新機(jī)制并不是基于補(bǔ)丁包更新的機(jī)制,傳統(tǒng)的熱更新經(jīng)常對(duì)多個(gè)版本之間分別生成補(bǔ)丁包,按順序下載補(bǔ)丁包并更新到最新版本。Cocos 的熱更新機(jī)制通過(guò)直接比較最新版本和本地版本的差異來(lái)生成差異列表并更新。
cocos熱更概述
manifest
了解cocos熱更之前,先要了解manifest。在cocos中,manifest是一種文件格式,其對(duì)應(yīng)的文件簡(jiǎn)稱(chēng)資源描述文件,是用來(lái)描述本地或遠(yuǎn)程包含的資源列表及資源版本。
manifest格式是仿照json格式,其關(guān)鍵字段的含義如下 :
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{ "packageUrl" : 遠(yuǎn)程資源的本地緩存根路徑 "remoteVersionUrl" : [可選項(xiàng)] 遠(yuǎn)程版本文件的路徑,用來(lái)判斷服務(wù)器端是否有新版本的資源 "remoteManifestUrl" : 遠(yuǎn)程資源 Manifest 文件的路徑,包含版本信息以及所有資源信息 "version" : 資源的版本 "engineVersion" : 引擎版本 "assets" : 所有資源列表 "key" : 資源的相對(duì)路徑(相對(duì)于資源根目錄) "md5" : md5 值代表資源文件的版本信息 "compressed" : [可選項(xiàng)] 如果值為 true ,文件被下載后會(huì)自動(dòng)被解壓,目前僅支持 zip 壓縮格式 "size" : [可選項(xiàng)] 文件的字節(jié)尺寸,用于快速獲取進(jìn)度信息 "searchPaths" : 需要添加到 FileUtils 中的搜索路徑列表 } |
Manifest 文件可以通過(guò) Cocos Creator 熱更新范例中的 Version Generator腳本 來(lái)自動(dòng)生成。
工程資源和游戲包內(nèi)資源的區(qū)別
大家在創(chuàng)建一個(gè) Cocos Creator 工程的時(shí)候,可以看到它的目錄下有 assets 目錄,里面保存了你的場(chǎng)景、腳本、prefab 等,對(duì)應(yīng)編輯器中的 assets 面板。但是這些工程資源并不等同于打包后的資源,在使用構(gòu)建面板構(gòu)建原生版本時(shí),我們會(huì)在構(gòu)建目錄下找到 res 和 src 文件夾,這兩個(gè)文件夾內(nèi)保存的才是真正讓游戲運(yùn)行起來(lái)的游戲包內(nèi)資源。其中 src 包含所有腳本,res 包含所有資源。
所以我們的資源熱更新自然應(yīng)該更新構(gòu)建出來(lái)的資源,而不是工程的 assets 目錄。
在creator2.4.3中,重構(gòu)了資源管理模塊,采用bundle模塊化管理資源。這里分享一個(gè)通過(guò)uuid來(lái)獲取資源路徑的API
1
|
cc.assetmanager.utils.getUrlWithUuid //轉(zhuǎn)換 uuid 為 url,這里返回的url是運(yùn)行時(shí)游戲包內(nèi)的資源路徑 |
searchPaths搜索路徑
在談到熱更之前,關(guān)于searchPaths的概念,有必要先了解一下。在大多數(shù)的時(shí)候,我們描述一個(gè)文件的路徑,都會(huì)基于一個(gè)”根目錄“去給到對(duì)應(yīng)的”相對(duì)路徑“,并不會(huì)直接寫(xiě)死成”絕對(duì)路徑“,這樣更利于維護(hù)、遷移。在游戲開(kāi)發(fā)中,其實(shí)我們”根目錄“也是很難保證其確定性、唯一性。就拿熱更功能而言,我們有一個(gè)圖片,假設(shè)其對(duì)應(yīng)bundle目錄(默認(rèn)是resources)的相對(duì)路徑是 ”./png/icon1.png“,當(dāng)我們游戲版本更新,需要更新該圖片的時(shí)候,由于包內(nèi)的資源是不可寫(xiě)的,那我們只能讓其從另外一個(gè)地方讀取到新的圖片,為了保證代碼的一致性,如果我們可以改變其對(duì)應(yīng)的”根目錄“,那代碼中之前的相對(duì)路徑都不需要修改,就能找到新的圖片。
在creator中,其維護(hù)勒一套搜索路徑的策略。對(duì)應(yīng)的API可以查閱jsb.fileUtils.getSearchPaths、jsb.fileUtils.fullPathForFilename等。這里簡(jiǎn)述其原理。FileUtils中保存勒一個(gè)”根目錄“數(shù)組,index越低的優(yōu)先級(jí)越高,在查找資源的時(shí)候,我們?nèi)绻付ǖ氖?rdquo;相對(duì)路徑“,則其會(huì)按照searchPaths里面的”根目錄“的優(yōu)先級(jí),去拼接成”絕對(duì)路徑“去查找資源,如果路徑有效,找到勒文件,則會(huì)停止繼續(xù)尋找。
在游戲包的安裝目錄,肯定有一個(gè)目錄是存放我們打包后的各種腳本、資源,我們這里稱(chēng)之為”游戲包目錄“,在熱更邏輯中,我們需要指定一個(gè)”熱更目錄“來(lái)存放我們熱更的內(nèi)容,這兩個(gè)目錄都應(yīng)該設(shè)為搜索路徑,并且需要控制版本,使優(yōu)先級(jí)更高的目錄,對(duì)應(yīng)的搜索路徑優(yōu)先級(jí)也要越高,這樣,我們才能找到最新的文件。一般而言,”熱更目錄“的優(yōu)先級(jí)需要高于”游戲包目錄“。
cocos的基礎(chǔ)熱更流程
這是cocos官網(wǎng)資料的流程圖,注意,當(dāng)前流程是用戶(hù)安裝好 app 后,第一次檢查到服務(wù)端的版本更新的情況,完整的熱更流程會(huì)更為復(fù)雜一些,后面我們?cè)俾a(bǔ)充。
本文主要幫助大家理解熱更本身的流程邏輯,其各個(gè)細(xì)節(jié),如斷點(diǎn)續(xù)傳、下載進(jìn)度、并發(fā)下載、錯(cuò)誤檢測(cè)、解壓縮、錯(cuò)誤恢復(fù)等細(xì)節(jié)問(wèn)題,暫不討論。所以,把上訴流程圖,可簡(jiǎn)單概況為:
根據(jù)當(dāng)前包內(nèi)的manifest的remoteVersionUrl字段,去下載其當(dāng)前的版本描述文件,然后根據(jù)與本地的版本對(duì)比,若需要更新則更新到對(duì)應(yīng)最新版本,不然就不需要更新,繼續(xù)后續(xù)流程。
這里需要對(duì)其幾個(gè)關(guān)鍵點(diǎn),再細(xì)化剖析一下:
_localManifest:當(dāng)前包內(nèi)的manifest
首先,”游戲包目錄“內(nèi)應(yīng)該有一個(gè)默認(rèn)的manifest文件,描述當(dāng)前游戲版本("version"字段),這個(gè)manifest一般隨游戲包卸載、安裝來(lái)更新。然后在”熱更目錄“也會(huì)有一個(gè)manifest文件,描述當(dāng)前熱更目錄下的版本信息。我們每次啟動(dòng)游戲的時(shí)候都應(yīng)該判斷一下,當(dāng)前環(huán)境下,到底是”游戲包目錄“,還是”熱更目錄“才是最新的版本,來(lái)調(diào)整其對(duì)應(yīng)在searchPaths的優(yōu)先級(jí),較新的manifest也就稱(chēng)為當(dāng)前包內(nèi)的manifest,代碼中用_localManifest來(lái)記錄。
注意,上述cocos基礎(chǔ)熱更流程中,并沒(méi)有這一步,是因?yàn)槠浔硎玖鞒淌前谝淮伟惭b的情況,熱更目錄下是沒(méi)有manifest文件,所以_localManifest就是”游戲包目錄“,完整的熱更流程是需要做這一步判斷的。
上訴邏輯對(duì)應(yīng)的代碼,請(qǐng)參閱:AssetsManagerEx的init、loadLocalManifest等函數(shù)。
先請(qǐng)求遠(yuǎn)端版本manifest
在manifest的”remoteVersionUrl“字段中,其對(duì)應(yīng)的是遠(yuǎn)端服務(wù)器的版本文件,下面給到官方demo的一個(gè)version.manifest,便于大家理解
1
2
3
4
5
6
|
{ "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有一個(gè)“version”字段,這也是我們快速進(jìn)行版本對(duì)比的依據(jù)。下載version.manifest,然后再與本地_localManifest的版本對(duì)比,來(lái)檢測(cè)當(dāng)前包是否需要更新,這個(gè)過(guò)程代碼上一般命名為checkUpdate。
臨時(shí)文件夾的必要性
在熱更過(guò)程中,因?yàn)槲覀兪嵌鄠€(gè)資源依次下載的,這期間很可能出現(xiàn)各種問(wèn)題,所有,我們需要一個(gè)臨時(shí)文件夾來(lái)暫存我們的下載,等到全部文件下載結(jié)束后,還需要檢測(cè)文件是否完整,才能去替換“熱更目錄”下的舊資源,不要直接在“熱更目錄”上下載,一旦出現(xiàn)問(wèn)題,自己也搞不清那部分是新的,那部分是還是舊的。這種思路在程序設(shè)計(jì)中也可以借鑒體會(huì),我們負(fù)責(zé)的一些數(shù)據(jù)、字段的維護(hù),盡量能做到整體的替換更新,而不是到處隨意的去修改、賦值。
熱更是熱更差異化文件,是怎么做到這點(diǎn)的
在manifest文件中,"assets"字段下,記錄每個(gè)資源的key和md5信息,只需要遠(yuǎn)端的_remoteManifest下記錄的資源進(jìn)行對(duì)比,新的key則是新增資源,沒(méi)有的key則是需要?jiǎng)h除的資源,md5不同的就是需要更新的文件。
對(duì)應(yīng)的代碼,請(qǐng)參閱:Manifest的genDiff等函數(shù)。
熱更好之后,怎么讓其生效
當(dāng)我們熱更好了新的資源后,怎么在不需要調(diào)整代碼的情況下,讓其生效?哈哈,剛剛上文已經(jīng)介紹過(guò)了,我們調(diào)整我們的searchPaths,讓“熱更目錄”優(yōu)先級(jí)高于“游戲包目錄”即可。
上面的流程圖中,cocos推薦的是用cc.sys.localStorage把_localManifest對(duì)應(yīng)的路徑存儲(chǔ)起來(lái),并在后續(xù)app啟動(dòng)的開(kāi)始階段,就從cc.sys.localStorage讀取對(duì)應(yīng)路徑,設(shè)置到searchPaths中。
上訴方案固然可行,但是就一個(gè)完善的客戶(hù)端框架而言,尤其是針對(duì)多子項(xiàng)目的大廳類(lèi)游戲,個(gè)人認(rèn)為這種動(dòng)態(tài)存儲(chǔ)路徑、設(shè)置路徑并不是比較合適的方案。在架構(gòu)設(shè)計(jì)上,我們需要先確定好整個(gè)客戶(hù)端的“熱更目錄”,并確定好優(yōu)先級(jí),即整個(gè)項(xiàng)目的searchPaths都是按照我們?cè)O(shè)定的邏輯固定好,而不是動(dòng)態(tài)的去調(diào)整,這樣的好處是,在唯一的地方確定好searchPaths邏輯,之后僅需要根據(jù)邏輯,增刪對(duì)應(yīng)路徑下的資源即可,這樣應(yīng)該是更利于擴(kuò)展和維護(hù)的。但同樣需要注意,這種固定好searchPaths的方案,在app安裝替換的時(shí)候,要維護(hù)好新的“游戲包目錄”的版本與之前“熱更目錄”下的版本對(duì)比情況,如,app本地安裝升級(jí)后的版本比之前“熱更目錄”的版本更高,可以考慮把之前“熱更目錄”下的資源都清空掉,另外一種更麻煩的邏輯是,app安裝升級(jí)后的版本還是比“熱更目錄”版本低,這是要注意,“熱更目錄”存儲(chǔ)的是相對(duì)于升級(jí)前“游戲包目錄”的差異化文件,升級(jí)后“游戲包目錄”下的文件發(fā)生變化,那“熱更目錄”下的差異化文件就不一定能兼容當(dāng)前的“游戲包目錄”,這種情況也可以把“熱更目錄”情況,讓其重新去對(duì)比、熱更差異化文件。
舊的版本資源怎么處理
cocos的熱更的雖然是差異化文件,但是其manifest腳本是記錄勒對(duì)應(yīng)bundle所有的資源,我們是能知道哪些資源已經(jīng)不需要的,上文genDiff函數(shù)也提到過(guò),但是個(gè)人認(rèn)為,舊資源的刪除需要謹(jǐn)慎,至少也是確保新資源更新好后,再去刪除舊資源。
總結(jié)
如果讀者在消化勒上訴的一些知識(shí)后,利用cocos提供的基礎(chǔ)功能函數(shù),是完全可以徹底定制自己的熱更流程的。熱更,一言以蔽之,下載最新的遠(yuǎn)端資源替換當(dāng)前包體內(nèi)的就資源而已。比如一些小項(xiàng)目,完全可以整包的下載、替換,可以忽略其中版本對(duì)比、searchPath調(diào)整、文件校驗(yàn)等細(xì)節(jié)。
以上就是全面講解CocosCreator熱更新的詳細(xì)內(nèi)容,更多關(guān)于CocosCreator熱更新的資料請(qǐng)關(guān)注服務(wù)器之家其它相關(guān)文章!
原文鏈接:https://blog.csdn.net/qq_41211553/article/details/111559869