都有哪些原因会导致依赖远程资源的场景加载不成功?

Creator版本:2.0.5
平台:玩一玩

描述:
1,我们的场景切换时中间加了一个过渡场景,代码如下,这个LoadingScene的工作基本上就是preload下一个场景,然后再进去。
2,发布到线上以后,我们收到部分玩家反馈,会卡在这个LoadingScene 进不去下一个场景
3,联系上这些玩家以后,他们表示,之前能玩,能进去,是突然进不去了,他们并不是第一次就进不去,而且是前天能进去,今天就进不去了,在我映像中,如果一个场景进去过,它所依赖的远程资源,应该都已经下载到本地了,所以我非常纳闷为什么之后又进不去了,第一次进不去可能是网络原因导致远程资源下载不成功
4,根据我自己的测试,因为我的的场景没有设置延迟加载,所以如果下一个要加载的目标场景,如果图片加载不成功,或场景json文件出错或加载不成功都可能导致这种情况
5,我们的大部分资源都放在远程服务器

我的问题是:
1,这种问题线上版本如何精确定位?有什么办法可以收集到报错信息,因为我们自己无法重现,又不可能拿玩家的手机来测试
2,场景loading过程中失败,无法进入下一个场景,都有哪些原因会导致这种情况,我自己分析的可能不全面

怕帖子石沉大海,不好意思 @panda @jare @Knox @一下三位大佬


cc.Class({
    extends: cc.Component,

    properties: {
        tiplabel: cc.Label,
        progressBar: cc.ProgressBar,
        bg: cc.Node
    },

    onLoad() {
        this.progressBar.progress = 0
        if (cc.winSize.height > 1280) {
            this.bg.scale = cc.winSize.height / 1280
        }
        this.tiplabel.string = GlobalVar.dataMgr.getTips()

        if (cc.sys.platform === cc.sys.QQ_PLAY) { // 玩一玩当前版本会卡住,要等qq升级到7.9才修复,先让进度条跑一下
            this.progressBar.progress = 0.1 + Math.random() * 0.2
        }

        if (GlobalVar.hasBanner) {
            GlobalVar.adsMgr.hideBanner()
        }
    },

    start() {
        this.m_nextScene = GlobalVar.SceneTo || "Main"
        this.m_simulatorSpeed = 1.0

        this.m_curProgress = 0.1

        var onProgress = (completedCount, totalCount, item) => { //进度回调
            //cc.log("LoadingScene onProgress", completedCount, totalCount)

            this.m_updateTimeTotal = 0
            let percent = completedCount / totalCount
            this.m_curProgress = percent
        }

        cc.director.preloadScene(this.m_nextScene, onProgress, () => {
        })
    },

    update(dt) {//使得进度条更加顺滑,连贯
        if (this.m_curProgress) {
            if (this.progressBar.progress < this.m_curProgress) {
                this.progressBar.progress += dt * this.m_simulatorSpeed
            }
            else if (this.progressBar.progress >= 1 && !this.m_jumpToOtherScene) {
                GlobalVar.alreadyLoadedScenesMap[this.m_nextScene] = true
                cc.director.loadScene(this.m_nextScene)
                this.m_jumpToOtherScene = true
            }
        }
    },


    onDestroy() {
        if (GlobalVar.hasBanner) {
            GlobalVar.adsMgr.showBanner()
        }
    }
});
1赞

这个确实不好排查,目前也没啥好的办法收集报错信息,最好是让用户描述一下机型,然后自行验证看看

通常都是资源加载失败导致的,玩家出现的是没有跳转到下个场景还是黑屏?

没有跳转,主要是跟我反馈的玩家都不是第一次进不去,进去过然后第二天就进不去了

大佬们可以在qq主界面搜索美味冰工厂,体验一下我们的游戏,实地查看一下我所说的LoadingScene

谢谢啦

这个还是需要向玩家询问一下手机机型,然后进行反复测试进行重现,不然还是没办法找到问题所在。

可能到问题有: 资源加载失败导致切换场景到条件没有满足

场景json文件错误有可能吗?远资源加载失败的话,在网络没问题的情况下,重复多次进去,应该能加载成功。
有没有可能对应的远程资源已经下载到本地,但确是不完整的?引擎在创建本地文件缓存的时候会保证文件的正确性吗?
举个例子:一个json文件下载到一半,网络断了,本地会是什么情况?

谢谢啦!看来还是要想办法重现

看了一下玩一玩的下载资源的代码qqplay-downloader.js
像我箭头指向的两段,看起来,一个资源是有可能下载并没有成功,但对应的文件名没有删除的
在发起网络请求的时候,对应的文件就创建了,如果请求失败再删除这个文件,现实操作中有可能出现发起了网络请求,创建了文件,最后还没等到请求失败/下载成功,玩家就退出游戏了,那本地就有可能存在不完整的文件(还是空文件?)
这种情况应该用临时文件名来保证的吧? 玩一玩貌似没有提供重命名文件的接口,无法把临时文件改名为正式文件?。。。。。。所以说到底还是玩一玩的锅?

还有一个问题,我其实想到给玩家提供一个,修复按钮,删除本地文件缓存,但是文档(玩一玩的文档)里面都没有这个接口

你可以试看看这个接口,或者可以自己在 qqplay-downloader 中存储下载后到资源,然后在通过上面到 unlinkSync 进行删除

但是我还是觉得最好还是能重现问题比较好,这样就能看到具体的 log 信息,如果用猜测到话,还是不能保证具体发生的原因

结合我遇到的情况,我做出如下判断

用户前几次可以,这次你更新后不行,90%报了4916错误,原因在于,用户的50M缓存用完了,你新的内容无法下载或者无法加载到本地,导致资源不匹配,所以卡在切换场景上(虽然不一定卡哪里,但是我遇到最多的也是卡在切换场景上)。

如果是这种情况,我的做法是,在第一个场景判断用户的缓存是否超标(我是35M的资源,如果超过36M我就算他超),然后把所有缓存清掉,重新下载一遍所有资源。

搞定!

我们所有的资源加起来都没有超过15M哦。。

一次15M,第二次更新一点,变20M,多更几次,就超啦。

补充一下,如果你图片有修改,A图片略微改动变成B,那B加载到机器里面就算一个新的图片,以此类推

有道理,不过我发现玩一玩的上限是10M,而且是zip包的限制,我现在直接把所有资源都放到包里面了。。