cc.loader.onProgress加载第二次得时候是有bug吗 急!!

我在用cc.loader.onProgress 这个监听 判断加载完成后 执行界面跳转.但是

这个监听,在资源第一次加载的时候一切正常

但是当资源都加载过一遍 再次打开界面重新加载 发现传过来的completedCount = 0, totalCount = 0

推测 资源加载过后被缓存了所以不会走onProgress 但是 这个不合逻辑 或者说 一个api存在两种逻辑

我期望的是如同方法明一样监听加载进度.而不关心资源是缓存过了还是真的在加载.如果是缓存过了应该算闪一下就直接加载完毕那种才对.

请问是我理解有误还是使用有误? 应该如何解决这个问题?

另外 我关闭界面后执行
cc.loader.releaseRes(“Fight/images”);
也没办法释放资源还是传入completedCount = 0, totalCount = 0
并且UI花屏

版本2.0.5

progress:0.85 item:res/import/2b/2b324a93-e280-4a8f-97e7-0ec771085733.json
20:48:11.831 LoadingUI.js:35 completedCount = 73,totalCount=86,progress=0.85
20:48:11.832 LoadingUI.js:34 progress:0.85 item:res/import/8d/8dcbbff0-38af-4736-8852-148e99ff4911.json
20:48:11.833 LoadingUI.js:35 completedCount = 73,totalCount=86,progress=0.85
20:48:11.835 LoadingUI.js:34 progress:0.86 item:res/import/2a/2aecce6a-bcfc-4f60-a133-b68da056d8de.json
20:48:11.838 LoadingUI.js:35 completedCount = 74,totalCount=86,progress=0.86
20:48:11.839 LoadingUI.js:34 progress:0.86 item:res/import/8d/8dcbbff0-38af-4736-8852-148e99ff4911.json
20:48:11.840 LoadingUI.js:35 completedCount = 74,totalCount=86,progress=0.86
20:48:11.842 LoadingUI.js:34 progress:0.87 item:res/import/ab/ab342386-7bfc-4df9-9903-511012e86457.json
20:48:11.843 LoadingUI.js:35 completedCount = 75,totalCount=86,progress=0.87
20:48:11.845 LoadingUI.js:34 progress:0.87 item:res/import/8d/8dcbbff0-38af-4736-8852-148e99ff4911.json
20:48:11.846 LoadingUI.js:35 completedCount = 75,totalCount=86,progress=0.87
20:48:11.848 LoadingUI.js:34 progress:0.88 item:res/import/24/2444d6db-6135-480c-825a-2e557a7d582a.json
20:48:11.850 LoadingUI.js:35 completedCount = 76,totalCount=86,progress=0.88
20:48:11.851 LoadingUI.js:34 progress:0.88 item:res/import/8d/8dcbbff0-38af-4736-8852-148e99ff4911.json
20:48:11.852 LoadingUI.js:35 completedCount = 76,totalCount=86,progress=0.88
20:48:11.854 LoadingUI.js:34 progress:0.90 item:res/import/8e/8e6bd8e0-1fe6-42ce-9e8b-32778ae1565b.json
20:48:11.855 LoadingUI.js:35 completedCount = 77,totalCount=86,progress=0.90
20:48:11.857 LoadingUI.js:34 progress:0.90 item:res/import/8d/8dcbbff0-38af-4736-8852-148e99ff4911.json
20:48:11.859 LoadingUI.js:35 completedCount = 77,totalCount=86,progress=0.90
20:48:11.861

还有 我发现 这个问题的地方 加载进度会打印两遍 但是item看id不是一样的
有多个监听吗?

sos

是否提供给下onProgress代码,看看具体情况?

progressCallback中的totalCount参数指的是加载这个资源所需要加载的依赖项的个数,比如图片资源如果加载按SpriteFrame类型进行加载则要比按Texture2D类型加载要多一个依赖项,即多加载一个SpriteFrame。
所以如果totalCount为0则表示加载这个资源的话不需要再加载任何依赖项,直接可以使用。
NewProject.zip (585.5 KB)我这里有个demo可以参考一下。

另外最好给下你的加载代码或者是demo,这样也方便看问题

主要是代码涉及到服务端等等 不太好直接提供.

我写下代码吧:

我有一个通用的加载界面,然后需要加载界面的时候调用如下代码:

           UI.openUI("Loading/FightLoadingUI", (ui, uijs) => {

                let onFinish = function () {
                    UI.closeUI();
                    UI.openUI("Fight/FightUI");
                };
                uijs.setLoad(onFinish);
                GlobalRes.loadFight();

            });

这段代码做这些事件:
1.显示loading界面
2.设置cc.loader.onProgress
3.load一些资源

设置load也是很按demo里面做法 没特别操作:

setLoad(callback) {
cc.loader.onProgress = null;
cc.loader.onProgress = (completedCount, totalCount, item) => {
if (totalCount == 0) {
totalCount = 1;
completedCount = 1;
cc.error(“没有加载任务”);

            // return;
        }


        let progress = (completedCount / totalCount).toFixed(2);
      
        if (this.progressBar) {

            this.progressBar.progress = progress;
            this.label.string = progress * 100 + "%";
        } else {
            cc.log("??");
        }

        if (!this.finish && item && item.uuid && completedCount == totalCount) {
            // self.loadBar.fillRange = progress;
            this.finish = true;
            cc.loader.onProgress = null;
            callback();
         
        }


    };
},

设置完loader之后就开始加载我需要的资源

loadFight() {
this.count = 0;
this.loadCount = 0;

    cc.error("加载地图:" + DD.room.mapname);

    GlobalRes.loadRes('Fight/maps/' + DD.room.type + "/" + DD.room.mapname, (err, data) => {



        GlobalRes.tmxAsset = data;
        cc.error("加载地图成功:" + DD.room.mapname);
        // this.tiledMap.tmxAsset = data;
        // this.init2();

    });



    GlobalRes.loadRes("Fight/sounds/moving", (err, data) => { 
        GlobalRes.moving = data;//移动音效
    });
    GlobalRes.loadRes("Fight/sounds/nmoving", (err, data) => { 
        GlobalRes.nmoving = data;//移动音效
    });

    // GlobalRes.playEffect("Fight/sounds/nmoving");

    GlobalRes.loadRes("Fight/GameOverUI", (err, data) => { //加载战斗结果面板
        GlobalRes.GameOverUIPrefab = data;
    });

}

GlobalRes.loadRes这个方法其实就是 cc.loader.loadRes 封装一下做各日志

以上 在加载第一次资源的时候没任何问题, 但是如果资源加载过了 再次加载
cc.loader.onProgress 就会传入count = 0

我猜测就是因为资源被缓存 导致第二次加载没有走加载逻辑.

是这样的, 我需要加载 好几个资源

例如
xx prefab
xx image
xx json
xx tiledmap

其他资源都是固定的 但是 tiledmap 是根据进入房间不同 加载不同的tiledmap

并且加载完tiledmap 之后 会有相应的回调赋值.

然而cc.loader.onProgress 在检测 加载第一个资源 后就直接返回totalCount =0
后面几个资源都没有去判断了.

导致我的tiledmap 还没加载完就跳转了界面 导致其他问题.

你看下我给你的回复,第一次加载完后,如果重复加载,totalCount是会为0的,这代表加载这个资源所需要加载的item数为0。这里有什么问题么?如果totalCount如果为0就让进度条显示100%就行
比如加载一个texture2d,它所要加载的就是对应的json,png和texture2d,所以totalCount给你的就是3.
如果你填的type是spriteFrame的话,totalCount就是4,也就是json+png+texture2d+cc.SpriteFrame
你已经加载过的,只要没有release掉,那么这些都不需要加载,也就是加载的item数为0

NewProject.zip (598.7 KB)

我用你做的demo 修改下代码重现下

第一次点击load按钮

加载正常

第二次点击load按钮

弹出了两次加载记录

但是加载应该是一个整体的进度 而不是每次加载就弹出一个进度

也就是说 日志里面不应该没有加载任务记录

你看看我上传的demo,然后多点击几次load按钮

我的需求是:
1.打开个跳转界面显示进度条 加载完后跳转界面
2.跳转界面之前 我有一堆各种各样的资源要加载.

现在的问题是,cc.loader.onProgress 我设置的是全局的,单个资源没有设置 cc.loader.onProgress

但是第二次加载资源的时候 系统判定资源被加载过了直接就执行 cc.loader.onProgress 导致我那个显示进度条的方法异常.

我期望的是既然是全局的加载回调就应该是全局的进度 也就是totalCount 从来都不应该为0

或者说是我对这个方法理解有误,有没有什么解决办法

另外 我发现onProgress 这个接口在资源加载完毕就直接触发了

但是我在加载资源里面往往会有一些初始化和赋值等等callback代码. 是否应该改为执行完callback之后才判定加载完毕比较好?

为什么我会在意这个 是因为 我在加载预制体界面的时候 发现一直有一小段黑屏的画面. 而不是加载界面直接过渡到新界面.是因为资源加载完就直接触发了onProgress 然后判断加载完毕显示新界面并且关闭加载界面. 但是中间有一小段新界面的初始化过程 导致没有完全衔接上.(有几帧黑屏)

我说的黑屏问题就例如如下被注释掉的部分代码代码:

1.我在load里面把图片存起来
this.tex = res;

2.全部加载完毕后 我期望直接就能显示这个tex

if (item && item.uuid && completedCount == totalCount) {
            cc.loader.onProgress = null;
            // this.sprite.spriteFrame = this.tex;
            cc.error("loaded.................................");
        }

但是tex这个时候为空.因为onProgress 在资源加载完毕后就直接触发了.

我不知道你的进度条是什么形式的。
一种是两个进度条的,一个进度条是总进度,一个进度条是单个文件的进度,类似:

这种情况下单个文件的进度就是onProgress里面的completedCount/totalCount
总进度已加载完成的文件数/总文件数,总文件数由你传进去的参数决定,已加载完成的文件数通过load方法的onComplete回调去计数。
这是一种

另外一种就是一个总进度,这个时候就得判断一下了,如果你传进来需要加载的文件个数为1个,则进度条的进度和单个文件的onProgress进度一样。
如果需要加载的文件个数为多个,则进度条的进度和前面方法里面的总进度一样。

我的进度条就只只有一个总的 但是没法像你说的那样判断因为传入的totalCount 是0 并且onProgress 不知道为什么只触发了一遍.

导致我没办法判断加载是否结束

而且…
你可以多点几次我的demo

当所有资源都加载过了之后
更是没办法判断是否加载完成了.

全都是传入的totalCount = 0
我根本就没办法判断是否加载完成 什么时候跳转界面

totalCount 为0说明已经加载过了 直接跳转不行吗

你可以看看我发的demo 当你要加载多个资源的时候 请问你怎么跳转 什么时候跳转

NewProject.zip (700.7 KB)
看demo,当打印load finished and todo change scene的时候就可以跳转了。当加载多个资源的时候,你可以通过onComplete回调进行计数,从而判断有没有加载完成

另外,不建议用cc.loader.onProgress,最好可以用cc.loader.load函数传onProgress参数进去

你说的用计数方式实现进度条 这个我已经实现了.
但是这个的缺点是没办法精确计数,只能像1/3 2/3 3/3的跳跃式进度.

如果不建议用cc.loader.onProgress 那就基本上等于 加载多个资源 没办法实现进度条 或者说 cc.loader.onProgress 这个方法只适合加载单个资源或者第一次加载资源.

如果涉及到需要重复加载某个资源则不要使用cc.loader.onProgress 例如我需要重复打开战斗界面.除非修复了cc.loader.onProgress的bug.


我更倾向于修复掉cc.loader.onProgress的这个bug或者引擎是否能提供一个可用的全局进度条(之前我看介绍是可以把cc.loader.onProgress 当做全局进度条)

我简单的看了下cc.loader.onProgress的源码,之所以第二次加载会出现这些问题,原因是资源的某个计数数组 在加载完后被清空掉了.导致第二次执行加载方法的时候没有正确的传入completedCount和 totalCount
希望引擎组能修复下这个问题,

也就是说completedCount和 totalCount 根本就不应该存在 0这个返回数值,但是引擎组把这种情况当做一种缓存的处理结果直接返回了想让开发者去处理,就产生了我遇到的这种问题.

然而 作为一个开发者 当我使用这个接口的时候 我压根就不想去关心资源是从硬盘还是内存获取的 ,不关心加载快和慢这些问题.只希望进度能正确的按照这个接口原本意思返回对应的值.