1. 程式人生 > >creator 2.0版本對於preloadScene函數獲取加載進度

creator 2.0版本對於preloadScene函數獲取加載進度

can error emit 技術 當前 ould truct adr ==

有時候,當我們場景上掛載的資源過多時,我們使用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("加載完成");
         } } }); }

creator 2.0版本對於preloadScene函數獲取加載進度