有时候,当我们场景上挂载的资源过多时,我们使用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("加载完成");
} } }); }