prefab 在编辑器中直接instantiate的bug

需求是这样,在编辑器阶段通过预设好的prefab自动生成道路(主要是提供预览,微调后可以直接在游戏中使用)

第一次自动生成的prefab节点是正常的(假设生成了两个节点)。
然后切换回脚本,随便改个地方保存,再切回编辑器,这个时候脚本会再编辑器中被重新加载
然后之前生成的两个prefab节点就出问题了,体现在两个节点在选择的时候,直接变成多选状态(不管点击哪个节点,这两个节点都同时变成选中状态),如果此时锁定节点,会发现两个节点同时被上锁了。简单来说,就是两个节点实际上变成了同一个节点,后面的节点覆盖了前面的节点。(但是很奇怪的是,编辑器上看着还是两个)

并且这种情况下生成的prefab节点,属性面板中的取消prefab关联是不可用的。(正常从assets中拖到场景中的prefab没这个问题)

之前做个了赛车,也用这种方法往Z轴负方向平铺了一段路(Plane),给路和车分别加上物理碰撞,然后车子在第一个路面正常行驶,到第二个路面直接掉下去了。。。其实也是类似的bug,第二个路面实际上并不存在或是实际位置并不在那里,但是很奇怪的是视觉上仍然存在。

视频链接:

链接: https://pan.baidu.com/s/1nNFY1vtcYUVrz6iBYyoLXA 密码: 8vb5

版本:V3.3.2
系统:Mac

@arsen2010

1赞

经测试,基本可以确定是prefab本身的bug,通过同一个prefab创建的对象,不管有多少个,脚本重载后,都会被认定是同一个。表现在:1、选中一个其他也会被选中。2、锁定一个其他也被锁定。3、删除一个其他也被删除。(因为本身是全选状态)

同样的使用一个普通的Node(不制作成prefab) 来作为 instantiate 的参数就没这个问题。

收到,晚点回复你

麻烦你把 prefab 资源发上来一下,初步定位到一个已知问题点

你是自己通过代码,在编辑器里实例化prefab?

PlaneBlack.prefab.zip (860 字节)

其实就是最简单的一个plane,用的都是系统自带的材质

是的,之前2.4经常这么写没出毛病

像上面的代码,按照视频里面操作之后,两个节点都变成Node2了,实际上应该是一个Node1 一个Node2才对。
image

编辑器实例化Prefab和运行时是不太一样的,在编辑器里创建Prefab实例是要添加上PrefabInstance这个类的实例的,目前还没有公开编辑器中创建Prefab实例的方法(编辑器专用的方法),所以需要手动添加一下。

import { _decorator, Component, Node, CCBoolean, Prefab, instantiate } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('TestPrefab')
export class TestPrefab extends Component {
    // [1]
    // dummy = '';

    // [2]
    // @property
    // serializableDummy = 0;
    @property({type: Prefab})
    public prefab: Prefab = null;

    @property()
    private _build: boolean = false;

    @property(CCBoolean)
    set build(v: boolean) {
        if (v) {
            v = false;
            this.buildRoad();
        }

        this._build = v;
    }
    get build() {
        return this._build;
    }

    private createPrefabInstance(node: Node) {
        // @ts-ignore
        const prefabInfo = node._prefab;
        if (prefabInfo) {
            const prefabInstance = new Prefab._utils.PrefabInstance();
            prefabInstance.fileId = node.uuid;
            prefabInfo.instance = prefabInstance;
        }
    }

    private buildRoad() {
        this.node.removeAllChildren();
        const nd1 = instantiate(this.prefab);
        nd1.name = 'Node1';
        this.createPrefabInstance(nd1);
        this.node.addChild(nd1);
        nd1.setPosition(0, 0, 0);

        const nd2 = instantiate(this.prefab);
        nd2.name = 'Node2';
        this.createPrefabInstance(nd2);
        this.node.addChild(nd2);
        nd2.setPosition(0, 0, -10);
    }
}

好的,十分感谢

该主题在最后一个回复创建后14天后自动关闭。不再允许新的回复。