有時候,當我們場景上掛載的資源過多時,我們使用cc.director.loadScene切換場景時會等一段時間才會切換過去,這對游戲的體驗是相當不好的。所以我們可以使用cc.director.preloadScene來進行預加載,如:
cc.director.preloadScene("sceneName", function () { cc.director.loadScene("sceneName"); });
同時搭載一個加載進度條來實現顯示加載進度,優化游戲體驗:
那么如何獲取加載時的進度呢?
在Cocos creator 2.0版本之前,我們可以使用下面這樣的方法:
cc.loader.onProgress = function (completedCount, totalCount, item){ //先開監聽 this.loading.progress = completedCount/totalCount; this.loadLabel.string = Math.floor(completedCount/totalCount * 100) + "%"; }.bind(this); cc.director.preloadScene("sceneName", function () { cc.log("加載成功"); });
loading就是你在腳本中綁定的進度條組件。
Cocos creator升級到2.0版本后,onProgress貌似就無法使用了,所以上述那個方法無法獲取到加載進度,但是在cc.director.preloadScene這個函數中新增了一個參數:
所以我們可以通過這個參數來獲取加載的進度:
cc.director.preloadScene("sceneName", this.onProgress.bind(this), function(){ cc.log("加載成功"); }) onProgress :function(completedCount, totalCount, item){ this.loading.progress = completedCount/totalCount; this.loadLabel.string = Math.floor(completedCount/totalCount * 100) + "%"; }
其實無論是預加載場景還是加載資源,本質調用的還是cc.loader.load這個api,看底層代碼可以知道:
預加載場景:
preloadScene: function (sceneName, onProgress, onLoaded) { if (onLoaded === undefined) { onLoaded = onProgress; onProgress = null; } var info = this._getSceneUuid(sceneName); if (info) { this.emit(cc.Director.EVENT_BEFORE_SCENE_LOADING, sceneName); cc.loader.load({ uuid: info.uuid, type: 'uuid' }, onProgress, function (error, asset) { if (error) { cc.errorID(1210, sceneName, error.message); } if (onLoaded) { onLoaded(error, asset); } }); } else { var error = 'Can not preload the scene "' + sceneName + '" because it is not in the build settings.'; onLoaded(new Error(error)); cc.error('preloadScene: ' + error); } },
加載資源:
proto.loadResDir = function (url, type, progressCallback, completeCallback) { var args = this._parseLoadResArgs(type, progressCallback, completeCallback); type = args.type; progressCallback = args.onProgress; completeCallback = args.onComplete; var urls = []; var uuids = resources.getUuidArray(url, type, urls); this._loadResUuids(uuids, progressCallback, function (errors, assetRes, urlRes) { // The spriteFrame url in spriteAtlas will be removed after build project // To show users the exact structure in asset panel, we need to return the spriteFrame assets in spriteAtlas let assetResLength = assetRes.length; for (let i = 0; i < assetResLength; ++i) { if (assetRes[i] instanceof cc.SpriteAtlas) { let spriteFrames = assetRes[i].getSpriteFrames(); for (let k in spriteFrames) { let sf = spriteFrames[k]; assetRes.push(sf); if (urlRes) { urlRes.push(`${urlRes[i]}/${sf.name}`); } } } } completeCallback && completeCallback(errors, assetRes, urlRes); }, urls); };
proto._loadResUuids = function (uuids, progressCallback, completeCallback, urls) { if (uuids.length > 0) { var self = this; var res = uuids.map(function (uuid) { return { type: 'uuid', uuid: uuid } }); this.load(res, progressCallback, function (errors, items) { if (completeCallback) { var assetRes = []; var urlRes = urls && []; for (var i = 0; i < res.length; ++i) { var uuid = res[i].uuid; var id = this._getReferenceKey(uuid); var item = items.getContent(id); if (item) { // should not release these assets, even if they are static referenced in the scene. self.setAutoReleaseRecursively(uuid, false); assetRes.push(item); if (urlRes) { urlRes.push(urls[i]); } } } if (urls) { completeCallback(errors, assetRes, urlRes); } else { completeCallback(errors, assetRes); } } }); } else { if (completeCallback) { callInNextTick(function () { if (urls) { completeCallback(null, [], []); } else { completeCallback(null, []); } }); } } };
而cc.loader.load的內部實現的參數中就是帶有這個回調函數的
所以我們還可以這樣寫來獲取加載場景的進度:
var info = cc.director._getSceneUuid(this.sceneName); var self = this; if (info) { cc.loader.load({ uuid: info.uuid, type: 'uuid' }, function(completedCount, totalCount, item){ cc.log("已完成Items:" + completedCount); cc.log("全部Items:" + totalCount); cc.log("當前Item:" + item.url); self._loadingNextStep = parseInt(completedCount / totalCount * 100); cc.log("加載進度:" + self._loadingNextStep); }, function(error, asset){ if (error) { cc.errorID(1210, this.sceneName, error.message); } else { cc.log("加載完成");
} } }); }