大廳+子游戲的模式,在棋牌類型、教育類型遊戲中比較常見,一般是安裝包裏面只有大廳的資源和代碼,而後子游戲根據需求以熱更新的方式下載來提供給玩家。ios
以前一直負責的是cocos2dx-lua的開發,lua做爲腳本語言,很是適合作熱更新及大廳+子游戲模式的開發。而cocos creator使用的是js或者ts,做爲腳本語言也是很方便作熱更新的,可是js編譯是把全部的腳本編譯成一個單獨的js文件,若是不作調整,會致使全部的大廳+遊戲代碼編譯成一個單獨的js文件,是不太方便作成大廳+子游戲的模式的,這裏要討論的就是如何調整,以作成大廳+子游戲的模式。app
首先就是要將大廳、子游戲分開來構建了,要不就是建立單獨的大廳+子游戲工程,要不就是將大廳或者子游戲的代碼、資源拷貝到一個構建工程,而後用命令行工具或者直接使用GUI工具構建。我這邊沒有單獨分開建立工程,選擇的是在構建的時候經過腳本拷貝相關的資源,而後單獨構建。編輯器
分開構建/編譯好了資源以後,就是在app中怎麼使用了。在lua版本中,引擎的資源加載方式是直接讀取指定目錄的腳本/資源,因此咱們只要先將子游戲的腳本/資源下載好,再引入指定目錄的腳本就能夠了。js做爲腳本資源,思路上咱們也是讀取對應目錄的腳本,可是在creator版本中,引擎封裝了一套資源加載工具,每一個資源對應一個uuid,訪問資源的時候是使用uuid去尋找資源(咱們使用cc.loader.loadRes傳入的是帶資源目錄的url,內部會根據這個url找到uuid再來加載資源),構建/編譯項目的時候,會生成一個setting.js/jsc的文件,這個文件就是uuid和實際資源路徑的對應表。因此咱們須要作的就是如何引入子游戲生成的這個setting文件。參考論壇網友的思路,就是引入另一個js腳本,在該腳本中再去讀取對應子游戲的setting文件,合併到大廳的setting配置中,而後再跳轉到對應的遊戲場景,上代碼:工具
// 首先仍是要設置好搜索路徑 var searchPaths = jsb.fileUtils.getSearchPaths(); searchPaths.unshift(cc.JS_DIR); jsb.fileUtils.setSearchPaths(searchPaths); // 判斷是否已經加載過子游戲的setting if (!cc.gameSetting){ window.require(js_path + 'src/settings.js'); settings = window._CCSettings; window._CCSettings = undefined; // 防止重複加載腳本 if (!cc.jsList[js_path]){ require(js_path + 'src/' + (settings.debug ? 'project.dev.js' : 'project.js')); cc.jsList[js_path] = true } } else{ settings = cc.gameSetting } // 合併assetTypes var gameAssetTypes = settings.assetTypes; settings.assetTypes = baseSetting.assetTypes; if (gameAssetTypes && settings.assetTypes){ for (var typeIndex in gameAssetTypes) { var type = gameAssetTypes[typeIndex]; //不包含就塞到settings裏面去 if (settings.assetTypes.indexOf(type) == -1) { settings.assetTypes.push(type); } } for (var uuidKey in settings.rawAssets.assets) { var index = settings.rawAssets.assets[uuidKey][1]; var type1 = gameAssetTypes[index]; for (var typeIndex in settings.assetTypes) { var type2 = settings.assetTypes[typeIndex]; if (type1 == type2) { settings.rawAssets.assets[uuidKey][1] = parseInt(typeIndex); } } } } // 調整資源配置 for (var assetkey in baseSetting.packedAssets) { settings.packedAssets[assetkey] = baseSetting.packedAssets[assetkey]; } //動態資源合併 for (var uuidKey in baseSetting.rawAssets.assets) { settings.rawAssets.assets[uuidKey] = baseSetting.rawAssets.assets[uuidKey]; } //場景合併 for (var sceneKey in baseSetting.scenes) { if (settings.scenes.indexOf(baseSetting.scenes[sceneKey]) == -1){ settings.scenes.push(baseSetting.scenes[sceneKey]); } } // uuid合併 for (var uuidKey in baseSetting.uuids) { if (settings.uuids.indexOf(baseSetting.uuids[uuidKey]) == -1) { settings.uuids.push(baseSetting.uuids[uuidKey]) } }
上述代碼是在論壇網友提供的demo基礎上進行了部分調整,核心的邏輯仍是一致的:主要就是讀取對應子游戲的setting文件,而後合併到大廳的setting中,創建好子游戲資源的uuid對應關係,主要就能在遊戲中引入對應的遊戲資源。ui
論壇網友提供的demo中,從子游戲回到大廳,須要再引入一份獨立的js文件。可是個人理解是,在啓動大廳的時候已經將大廳的setting加入到內存中了,資源和uuid的對應關係已經創建,這個時候其實已經沒有必要再重複引入一次大廳的setting配置,再來合併。實際項目上,我也是按照個人理解,沒有再單獨的引入js文件實現從子游戲回到大廳,目前也暫時沒有碰到問題。lua
另外,由於思路上是大廳和子游戲要分開打包,在開發的過程當中咱們是能夠大廳+子游戲一塊兒開發。可是要注意的是,子游戲不能直接在編輯器中引用大廳的資源,好比子游戲的某個腳本是繼承自大廳的,,如:url
cc.Class({ extends: bg.GameModel, ... })
GamModel是大廳工程的代碼,在開發的過程當中,由於子游戲和大廳在一個工程,這樣直接使用是沒有問題的。若是將子游戲單獨打包,在構建的過程當中會報錯,不過仍是能構建成功,可是在運行的時候這個腳本組件就不會綁定到對應的節點上去,因此應該調整一下:spa
cc.Class({ extends: window.bg == undefined ? cc.Component : bg.GameModel, ... )}
這樣構建的過程當中不會報錯,腳本組件能正常的綁定到對應的節點上去。運行過程當中由於已經加載了大廳的代碼,因此這個三目運算的結果是取後面的bg.GameModel。命令行
實現環境:Cocos Creator 2.0.9 版本。以前使用2.10版本,一樣的代碼構建的工程,在win32模擬器上就會一直報錯,自帶模擬器對應的src目錄下的modular.js會出現錯誤,後來換成2.0.9版本,自編譯win32工程,再用模擬器運行就沒有問題了。在安卓和ios上到是都正常的。debug