From 85a5c7490bc4847322d17c1dba41c769ed8cef4a Mon Sep 17 00:00:00 2001 From: AZhan Date: Thu, 4 Dec 2025 15:15:50 +0800 Subject: [PATCH] Fix `PrefabResource` refCount was incorrect (#2864) (#2865) * fix: prefab refcount error --- packages/loader/src/prefab/PrefabParser.ts | 9 +++- .../resources/parser/HierarchyParser.ts | 34 ++++++------ tests/src/loader/PrefabResource.test.ts | 54 +++++++++++++++++++ 3 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 tests/src/loader/PrefabResource.test.ts diff --git a/packages/loader/src/prefab/PrefabParser.ts b/packages/loader/src/prefab/PrefabParser.ts index 6847d7745..5b5bdefd5 100644 --- a/packages/loader/src/prefab/PrefabParser.ts +++ b/packages/loader/src/prefab/PrefabParser.ts @@ -1,7 +1,7 @@ import { Engine, Entity } from "@galacean/engine-core"; +import { IEntity, IHierarchyFile, ParserContext, ParserType } from "../resource-deserialize"; import { HierarchyParser } from "../resource-deserialize/resources/parser/HierarchyParser"; import { PrefabResource } from "./PrefabResource"; -import { IHierarchyFile, ParserContext, ParserType } from "../resource-deserialize"; export class PrefabParser extends HierarchyParser> { static parse(engine: Engine, url: string, data: IHierarchyFile): Promise { @@ -20,6 +20,13 @@ export class PrefabParser extends HierarchyParser, path: string) { const { entityMap, components } = context; const componentsMap = {}; diff --git a/tests/src/loader/PrefabResource.test.ts b/tests/src/loader/PrefabResource.test.ts new file mode 100644 index 000000000..58a1c1628 --- /dev/null +++ b/tests/src/loader/PrefabResource.test.ts @@ -0,0 +1,54 @@ +import { expect, beforeAll, afterAll, describe, it } from "vitest"; +import { WebGLEngine } from "@galacean/engine-rhi-webgl"; +import type { IHierarchyFile } from "@galacean/engine-loader"; +import { PrefabParser } from "../../../packages/loader/src/prefab/PrefabParser"; + +let engine: WebGLEngine; + +beforeAll(async () => { + const canvas = document.createElement("canvas"); + canvas.width = 256; + canvas.height = 256; + engine = await WebGLEngine.create({ canvas }); +}); + +afterAll(() => { + engine?.destroy(); +}); + +describe("PrefabResource refCount", () => { + it("should increase and decrease with instantiated entities", async () => { + const prefabData: IHierarchyFile = { + entities: [ + { + id: "0", + name: "root", + components: [], + children: ["1"] + }, + { + id: "1", + name: "child", + parent: "0", + components: [] + } + ] + }; + + const prefab = await PrefabParser.parse(engine, "prefab.json", prefabData); + + expect(prefab.refCount).toBe(0); + + const instance1 = prefab.instantiate(); + const instance2 = prefab.instantiate(); + + // One ref count per templated entity in each instance (root + child). + expect(prefab.refCount).toBe(4); + + instance1.destroy(); + expect(prefab.refCount).toBe(2); + + instance2.destroy(); + expect(prefab.refCount).toBe(0); + }); +});