V3.6.2场景切换报错,有工程文件

  • Creator 版本: 3.6.2

  • 目标平台: Windows PC Chrome

  • 重现方式:运行工程进入Scene1,点击Run Scene2进入Scene2,再点击Run Scene1报错

  • 首个报错:

base-node.ts:649 Uncaught TypeError: Cannot read properties of null (reading 'length')
    at Scene.walk (base-node.ts:649:36)
    at Scene._load (scene.ts:327:14)
    at Director.runScene (director.ts:438:15)
    at Scene2.runScene1 (Scene2.ts:10:18)
    at EventHandler.emit (component-event-handler.ts:175:17)
    at Function.emitEvents (component-event-handler.ts:89:19)
    at Button._onTouchEnded (button.ts:861:35)
    at CallbacksInvoker.emit (callbacks-invoker.ts:344:34)
    at NodeEventProcessor.dispatchEvent (node-event-processor.ts:288:33)
    at Node.dispatchEvent (base-node.ts:1162:30)
  • 重现概率:必现

  • Scene1 代码:

import { _decorator, Component, Node, SceneAsset, director } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Scene1')
export class Scene1 extends Component {
    @property(SceneAsset)
    scene2: SceneAsset = null;

    runScene2() {
        director.runScene(this.scene2);
    }
}
  • Scene2 代码:
import { _decorator, Component, Node, SceneAsset, director } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Scene2')
export class Scene2 extends Component {
    @property(SceneAsset)
    scene1: SceneAsset = null;

    runScene1() {
        director.runScene(this.scene1);
    }
}
  • 复现工程:TestProject.zip (10.5 KB)
    (这个工程是用3.6.0版本创建的,忘了调成3.6.2,但3.6.2版本确实有这个问题)

感兴趣的朋友可以帮忙看看你们那边会不会异常,看看是不是只是我这边有环境有问题

本来怀疑是 Scene1 和 Scene2 组件中分别持有了 Scene2 和 Scene1 的 SceneAsset 资源导致的,但最新的情况是,我增加了一个 Scene3 ,然后将场景切换的顺序改为 Scene1 -> Scene2 -> Scene3 -> Scene1,结果是在 Scene3 切换到 Scene1 的时候产生了相同的错误

已经在github上建立了issue: https://github.com/cocos/cocos-engine/issues/13400
希望能早日解决

前辈,你这写法好少见,是有什么特殊的用处或好处吗,怎么不用官方文档的写法载入或者用 Asset Bundle的方法呀

    runScene1() {
    director.preloadScene("Scene1", () => {
        director.loadScene("Scene1")
    });

我的项目运行在APP内嵌的webview中,并且对加载的速度十分敏感,当我使用 preload + load 这种方式切换场景时,速度始终差强人意,所以在当我想办法提升切换场景的速度时,发现 runScene 是可以接收 SceneAssert 类型的参数的,于是尝试使用 runScene 的方法切换场景,结果是速度提升了非常多,不过后面就遇到了这里所说的问题

我在另一个帖子里面有讨论与此相关的一些问题 https://forum.cocos.org/t/topic/142671

奥奥哦,明白了

这种方式如果遇到 bundle 内场景重名直接无解

如果有场景重名的情况,恐怕不只这种方式会有问题,传统方式同样会有问题吧

另外目前在同一个 bundle 下好像是不允许场景重名的

export1

我说的不是一个 bundle 内

抱歉刚才弄错了,同一个 bundle 内场景也是可以重名的,刚才是因为在相同的目录下才不能重名

B46F095B-1A3F-4b8b-93BB-FE3804CC3719

同名的时候就不能用 bundle.loadScene 预加载场景了,可以换成这样的方式:

let bundle = assetManager.getBundle('bundleName'); // 由指定的 bundle 去加载
bundle.load('scenePath', SceneAsset, (error: Error, asset: SceneAsset) => {
    if (!error) director.runScene(asset);
});

使用路径就可以避免同一个 bundle 重名产生的问题了,不过重名应该是开发者应该避免的情况吧,同时由指定 bundle 去加载资源就不存在不同 bundle 的同名问题

其实如果 preloadScene 和 loadScene 的方式能够达到预期倒也不用像这样

太深奥了,你们赶紧看看把问题解决了让我做个笔记记录一下 :yum:

我只是指出用场景名的问题,而且你并不能避免别人开发的 bundle 内没有和你一样的场景名,除非强制规范命名,不过本来就可以通过 runScene 解决的问题,强制规范命名也没有意义

是的,这些都还是小问题,真正的问题在于 preloadScene + loadScene 的效果达不到预期,runScene 快一些但又会出错

issue 被关闭了,看来官方并不认为这是个缺陷,给到的说法有一点不能接受,等等看我后续的疑问还有没有人解答吧。