Skip to content

Conversation

@cptbtptpbcptdtptp
Copy link
Collaborator

@cptbtptpbcptdtptp cptbtptpbcptdtptp commented Dec 1, 2025

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

What is the current behavior? (You can also link to an open issue here)

What is the new behavior (if this is a feature change)?

Does this PR introduce a breaking change? (What changes might users need to make in their application due to this PR?)

Other information:

Summary by CodeRabbit

  • Refactor

    • Improved entity-data handling for prefabs and hierarchies to make prefab instantiation and template tracking more consistent and reliable, enhancing resource management.
  • Tests

    • Added unit tests to validate prefab resource reference-counting and lifecycle behavior during multiple instantiations and destruction.

✏️ Tip: You can customize this high-level summary in your review settings.

@cptbtptpbcptdtptp cptbtptpbcptdtptp self-assigned this Dec 1, 2025
@cptbtptpbcptdtptp cptbtptpbcptdtptp added bug Something isn't working resource Resource-related functions labels Dec 1, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

This PR changes HierarchyParser._applyEntityData from private to protected, adds a protected override in PrefabParser that marks entities as templates using the parser context resource, adjusts PrefabParser imports, and adds a unit test verifying PrefabResource refCount across instantiation/destruction of a two-entity prefab.

Changes

Cohort / File(s) Summary
Parser refactor & override
packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts, packages/loader/src/prefab/PrefabParser.ts
HierarchyParser._applyEntityData visibility changed from private to protected and its implementation consolidated; PrefabParser gains a protected override _applyEntityData(entity, entityConfig) that marks each entity as a template via this.context.resource; imports in PrefabParser.ts adjusted (added IEntity, IHierarchyFile, ParserContext, ParserType, removed duplicate import).
Tests
tests/src/loader/PrefabResource.test.ts
New unit test that constructs a two-entity prefab, parses it with PrefabParser.parse, instantiates/destroys two instances, and asserts PrefabResource refCount progression (0 → 4 → 2 → 0).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to entity transform application and layer handling in HierarchyParser._applyEntityData.
  • Verify PrefabParser._applyEntityData correctly marks templates without breaking parent behavior.
  • Validate test setup/teardown and that refCount assertions match resource lifecycle semantics.

Poem

Hops in the loader, a rabbit’s delight,
Private doors opened to broader daylight,
Templates are tagged as the parsers convene,
RefCounts climb, then fall — neat and serene,
I nibble a carrot and celebrate code clean. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: fixing an incorrect refCount issue in PrefabResource, which aligns with the core modifications to how entity data is applied and tracked.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f514d4 and 3ac3b5c.

📒 Files selected for processing (1)
  • packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts (3)
packages/core/src/Component.ts (1)
  • entity (71-73)
packages/loader/src/resource-deserialize/resources/schema/BasicSchema.ts (1)
  • IEntity (52-52)
packages/core/src/physics/shape/ColliderShape.ts (4)
  • position (103-105)
  • position (107-111)
  • rotation (90-92)
  • rotation (94-98)
🔇 Additional comments (1)
packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts (1)

65-80: Good refactoring to enable subclass customization.

Changing _applyEntityData from private to protected allows subclasses (like PrefabParser mentioned in the AI summary) to override this method and add custom behavior, such as marking entities as templates. The overall structure is sound, using nullish coalescing for optional properties and handling transforms via reflection or direct copying.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Dec 1, 2025

Codecov Report

❌ Patch coverage is 96.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 78.94%. Comparing base (46a0c5e) to head (3ac3b5c).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ce-deserialize/resources/parser/HierarchyParser.ts 94.11% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2864      +/-   ##
==========================================
- Coverage   79.65%   78.94%   -0.71%     
==========================================
  Files         857      857              
  Lines       93436    93517      +81     
  Branches     9372     9378       +6     
==========================================
- Hits        74422    73825     -597     
- Misses      18863    19543     +680     
+ Partials      151      149       -2     
Flag Coverage Δ
unittests 78.94% <96.00%> (-0.71%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/loader/src/prefab/PrefabParser.ts (1)

2-2: Verify _applyEntityData override doesn’t mis-mark prefab modification targets as templates

Overriding _applyEntityData to call _markAsTemplate(this.context.resource) looks like the right hook to ensure prefab template entities are registered against PrefabResource, which matches the new refCount test.

However, _applyEntityData is also invoked from HierarchyParser._parsePrefabModification when applying props to targetEntity inside instantiated prefabs. With this override in place, those modification targets will also be passed through _markAsTemplate, even though they’re instance entities coming from another prefab/GLTF resource.

Can you confirm this is intentional? If not, consider either:

  • Introducing a dedicated hook used only from _getEntityByConfig for initial template construction, or
  • Guarding the template-marking with a condition (e.g., only when applying the original entityConfig, not modification props).

Also applies to: 23-28

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46a0c5e and 8f514d4.

📒 Files selected for processing (3)
  • packages/loader/src/prefab/PrefabParser.ts (2 hunks)
  • packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts (2 hunks)
  • tests/src/loader/PrefabResource.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
tests/src/loader/PrefabResource.test.ts (2)
packages/core/src/base/EngineObject.ts (1)
  • engine (21-23)
packages/loader/src/prefab/PrefabParser.ts (1)
  • PrefabParser (6-38)
packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts (3)
packages/core/src/Component.ts (1)
  • entity (71-73)
packages/loader/src/resource-deserialize/resources/schema/BasicSchema.ts (1)
  • IEntity (52-52)
packages/core/src/physics/shape/ColliderShape.ts (4)
  • position (103-105)
  • position (107-111)
  • rotation (90-92)
  • rotation (94-98)
packages/loader/src/prefab/PrefabParser.ts (2)
packages/core/src/Component.ts (1)
  • entity (71-73)
packages/loader/src/resource-deserialize/resources/schema/BasicSchema.ts (1)
  • IEntity (52-52)
🪛 ESLint
packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts

[error] 361-361: Delete ·

(prettier/prettier)


[error] 363-363: Delete ·

(prettier/prettier)

🪛 GitHub Check: lint
packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts

[failure] 363-363:
Delete ·


[failure] 361-361:
Delete ·

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: e2e (22.x, 3/4)
  • GitHub Check: e2e (22.x, 4/4)
  • GitHub Check: e2e (22.x, 1/4)
  • GitHub Check: build (22.x, macos-latest)
  • GitHub Check: codecov
🔇 Additional comments (1)
tests/src/loader/PrefabResource.test.ts (1)

1-54: Prefab refCount regression test looks solid

The test cleanly exercises the instantiate/destroy lifecycle and asserts the expected refCount transitions; setup/teardown for WebGLEngine is reasonable for this scope.

Comment on lines +65 to +80
protected _applyEntityData(entity: Entity, entityConfig: IEntity = {}): Entity {
entity.isActive = entityConfig.isActive ?? entity.isActive;
entity.name = entityConfig.name ?? entity.name;
const transform = entity.transform;
const transformConfig = entityConfig.transform;
if (transformConfig) {
this._reflectionParser.parsePropsAndMethods(transform, transformConfig);
} else {
const { position, rotation, scale } = entityConfig;
if (position) transform.position.copyFrom(position);
if (rotation) transform.rotation.copyFrom(rotation);
if (scale) transform.scale.copyFrom(scale);
}
if (entityConfig.layer) entity.layer = entityConfig.layer;
return entity;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Layer assignment should allow 0 as a valid value

if (entityConfig.layer) entity.layer = entityConfig.layer; will not apply layer = 0, which makes it impossible to reset a previously non-zero layer back to 0 via config or prefab modifications.

Consider checking explicitly for undefined instead:

-    if (entityConfig.layer) entity.layer = entityConfig.layer;
+    if (entityConfig.layer !== undefined) {
+      entity.layer = entityConfig.layer;
+    }

This preserves the ability to set 0 while still ignoring absent layer config.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected _applyEntityData(entity: Entity, entityConfig: IEntity = {}): Entity {
entity.isActive = entityConfig.isActive ?? entity.isActive;
entity.name = entityConfig.name ?? entity.name;
const transform = entity.transform;
const transformConfig = entityConfig.transform;
if (transformConfig) {
this._reflectionParser.parsePropsAndMethods(transform, transformConfig);
} else {
const { position, rotation, scale } = entityConfig;
if (position) transform.position.copyFrom(position);
if (rotation) transform.rotation.copyFrom(rotation);
if (scale) transform.scale.copyFrom(scale);
}
if (entityConfig.layer) entity.layer = entityConfig.layer;
return entity;
}
protected _applyEntityData(entity: Entity, entityConfig: IEntity = {}): Entity {
entity.isActive = entityConfig.isActive ?? entity.isActive;
entity.name = entityConfig.name ?? entity.name;
const transform = entity.transform;
const transformConfig = entityConfig.transform;
if (transformConfig) {
this._reflectionParser.parsePropsAndMethods(transform, transformConfig);
} else {
const { position, rotation, scale } = entityConfig;
if (position) transform.position.copyFrom(position);
if (rotation) transform.rotation.copyFrom(rotation);
if (scale) transform.scale.copyFrom(scale);
}
if (entityConfig.layer !== undefined) {
entity.layer = entityConfig.layer;
}
return entity;
}
🤖 Prompt for AI Agents
In packages/loader/src/resource-deserialize/resources/parser/HierarchyParser.ts
around lines 65 to 80, the current layer assignment uses a truthy check which
skips applying layer when entityConfig.layer is 0; change the conditional to
explicitly check for undefined (e.g., if (entityConfig.layer !== undefined) ...)
so that zero is accepted while still ignoring absent layer config, then assign
entity.layer = entityConfig.layer when present.

@GuoLei1990 GuoLei1990 merged commit 01a56df into galacean:main Dec 1, 2025
11 of 12 checks passed
cptbtptpbcptdtptp added a commit to cptbtptpbcptdtptp/engine that referenced this pull request Dec 4, 2025
cptbtptpbcptdtptp added a commit that referenced this pull request Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working loader resource Resource-related functions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants