-
Notifications
You must be signed in to change notification settings - Fork 633
fix: Add Prefab Stage support for GameObject lookup #573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: Add Prefab Stage support for GameObject lookup #573
Conversation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reviewer's GuideAdds Prefab Stage awareness to GameObject lookup, path-based search, and hierarchy retrieval so tools like find_gameobjects work correctly when editing prefabs in isolation, while centralizing scene object enumeration logic in GameObjectLookup. Sequence diagram for by_path search in Prefab StagesequenceDiagram
actor User
participant ManageGameObjectCommon
participant GameObjectLookup
participant PrefabStageUtility
participant PrefabStage
User->>ManageGameObjectCommon: FindObjectsInternal(by_path, searchTerm, searchInactive, null)
ManageGameObjectCommon->>GameObjectLookup: GetAllSceneObjects(searchInactive)
GameObjectLookup->>PrefabStageUtility: GetCurrentPrefabStage()
PrefabStageUtility-->>GameObjectLookup: PrefabStage
GameObjectLookup->>PrefabStage: access prefabContentsRoot
loop each descendant GameObject
GameObjectLookup-->>ManageGameObjectCommon: GameObject
end
loop each GameObject
ManageGameObjectCommon->>ManageGameObjectCommon: GetGameObjectPath(go)
ManageGameObjectCommon->>ManageGameObjectCommon: compare path
alt path matches
ManageGameObjectCommon->>ManageGameObjectCommon: add to results
end
end
ManageGameObjectCommon-->>User: List GameObject results
Class diagram for updated GameObject lookup and scene utilitiesclassDiagram
class GameObjectLookup {
+IEnumerable~int~ SearchByPath(path, includeInactive)
+IEnumerable~GameObject~ GetAllSceneObjects(includeInactive)
+IEnumerable~GameObject~ GetObjectAndDescendants(root, includeInactive)
+string GetGameObjectPath(go)
}
class ManageGameObjectCommon {
+List~GameObject~ FindObjectsInternal(searchMode, searchTerm, searchInactive, rootSearchObject)
+IEnumerable~GameObject~ GetAllSceneObjects(includeInactive)
}
class ManageScene {
+object GetSceneHierarchyPaged(cmd)
}
class PrefabStageUtility {
+PrefabStage GetCurrentPrefabStage()
}
class PrefabStage {
+GameObject prefabContentsRoot
+Scene scene
}
class SceneManager {
+Scene GetActiveScene()
}
class EditorSceneManager {
+Scene GetActiveScene()
}
class Scene {
+bool IsValid()
+bool isLoaded
+string name
+GameObject[] GetRootGameObjects()
}
class GameObject {
+int GetInstanceID()
+Transform transform
}
class Transform {
+Transform Find(path)
+Transform[] GetComponentsInChildren(includeInactive)
+GameObject gameObject
}
ManageGameObjectCommon ..> GameObjectLookup : uses
ManageGameObjectCommon ..> SceneManager : uses
GameObjectLookup ..> SceneManager : uses
GameObjectLookup ..> PrefabStageUtility : uses
ManageScene ..> PrefabStageUtility : uses
ManageScene ..> EditorSceneManager : uses
PrefabStageUtility ..> PrefabStage : returns
PrefabStage ..> Scene : owns
SceneManager ..> Scene : returns
EditorSceneManager ..> Scene : returns
GameObject ..> Transform : has
Transform ..> GameObject : returns
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
📝 WalkthroughWalkthroughThe changes add Prefab Stage support to the GameObject lookup system, enabling the find_gameobjects tool and related utilities to locate objects when editing prefabs in isolation mode. Modifications include Prefab Stage detection, path-based search updates, and scene object enumeration for both standard and prefab editing contexts. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - I've found 2 issues, and left some high level feedback:
- The path-matching logic (
GetGameObjectPath+==/EndsWith) is now duplicated in multiple places (e.g.SearchByPathandManageGameObjectCommon); consider extracting a shared helper (e.g.MatchesPath(GameObject, string)) to keep the behavior consistent and easier to maintain. - In
ManageGameObjectCommon'sby_pathbranch (norootSearchObject), you're now always scanning all scene objects instead of usingGameObject.Findin normal scene mode, which may be a significant behavior and performance change; consider gating the manual scan on Prefab Stage only and falling back toGameObject.Findotherwise, as you did inGameObjectLookup.SearchByPath.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The path-matching logic (`GetGameObjectPath` + `==`/`EndsWith`) is now duplicated in multiple places (e.g. `SearchByPath` and `ManageGameObjectCommon`); consider extracting a shared helper (e.g. `MatchesPath(GameObject, string)`) to keep the behavior consistent and easier to maintain.
- In `ManageGameObjectCommon`'s `by_path` branch (no `rootSearchObject`), you're now always scanning all scene objects instead of using `GameObject.Find` in normal scene mode, which may be a significant behavior and performance change; consider gating the manual scan on Prefab Stage only and falling back to `GameObject.Find` otherwise, as you did in `GameObjectLookup.SearchByPath`.
## Individual Comments
### Comment 1
<location> `MCPForUnity/Editor/Helpers/GameObjectLookup.cs:160-161` </location>
<code_context>
+ foreach (var go in allObjects)
+ {
+ if (go == null) continue;
+ var goPath = GetGameObjectPath(go);
+ if (goPath == path || goPath.EndsWith("/" + path))
+ {
+ yield return go.GetInstanceID();
</code_context>
<issue_to_address>
**suggestion:** Path-matching logic is duplicated across helpers and tools; consider centralizing.
The `goPath == path || goPath.EndsWith("/" + path)` check is duplicated here and in `ManageGameObjectCommon` (both in the `by_path` branch and the fallback path search). Centralize this into a `SearchByPath`/`MatchesPath` helper on `GameObjectLookup` and call it from both places to keep semantics (case sensitivity, separators, search modes) consistent and easier to change later.
</issue_to_address>
### Comment 2
<location> `MCPForUnity/Editor/Tools/GameObjects/ManageGameObjectCommon.cs:92-100` </location>
<code_context>
-
- var found = GameObject.Find(path);
- if (found != null)
+ else
{
- yield return found.GetInstanceID();
</code_context>
<issue_to_address>
**suggestion (performance):** Full-scene scan for by_path searches may be unnecessarily expensive outside Prefab Stage.
When `rootSearchObject == null`, this now always calls `GetAllSceneObjects(searchInactive)` and scans the whole scene, even in normal mode. Previously, non-prefab lookups used `GameObject.Find(searchTerm)` for active objects, which is cheaper. For `searchInactive == false` outside Prefab Stage, consider keeping a fast path (e.g., `GameObject.Find` or `GameObjectLookup.SearchByPath`) and only falling back to a full scan when inactive objects are needed or when in Prefab Stage.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| var goPath = GetGameObjectPath(go); | ||
| if (goPath == path || goPath.EndsWith("/" + path)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Path-matching logic is duplicated across helpers and tools; consider centralizing.
The goPath == path || goPath.EndsWith("/" + path) check is duplicated here and in ManageGameObjectCommon (both in the by_path branch and the fallback path search). Centralize this into a SearchByPath/MatchesPath helper on GameObjectLookup and call it from both places to keep semantics (case sensitivity, separators, search modes) consistent and easier to change later.
| else | ||
| { | ||
| // In Prefab Stage, GameObject.Find() doesn't work, need to search manually | ||
| var allObjects = GetAllSceneObjects(searchInactive); | ||
| foreach (var go in allObjects) | ||
| { | ||
| if (go == null) continue; | ||
| var goPath = GameObjectLookup.GetGameObjectPath(go); | ||
| if (goPath == searchTerm || goPath.EndsWith("/" + searchTerm)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): Full-scene scan for by_path searches may be unnecessarily expensive outside Prefab Stage.
When rootSearchObject == null, this now always calls GetAllSceneObjects(searchInactive) and scans the whole scene, even in normal mode. Previously, non-prefab lookups used GameObject.Find(searchTerm) for active objects, which is cheaper. For searchInactive == false outside Prefab Stage, consider keeping a fast path (e.g., GameObject.Find or GameObjectLookup.SearchByPath) and only falling back to a full scan when inactive objects are needed or when in Prefab Stage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
MCPForUnity/Editor/Tools/ManageScene.cs (1)
612-616:ResolveGameObjectstill usesGameObject.Find()which doesn't work in Prefab Stage.While
GetSceneHierarchyPagednow correctly uses the Prefab Stage scene,ResolveGameObjectstill relies onGameObject.Find(s)for path-based lookups (Line 615). This will fail when specifying aparentparameter in Prefab Stage mode.Consider updating the path-based lookup to use the same pattern as
GameObjectLookup.SearchByPath:Proposed fix
// Path-based find (e.g., "Root/Child/GrandChild") if (s.Contains("/")) { - try { return GameObject.Find(s); } catch { } + try + { + var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); + if (prefabStage != null && prefabStage.prefabContentsRoot != null) + { + // Search in prefab contents + var root = prefabStage.prefabContentsRoot; + if (GetGameObjectPath(root) == s) return root; + var found = root.transform.Find(s); + if (found != null) return found.gameObject; + // Try relative path from root + foreach (Transform t in root.GetComponentsInChildren<Transform>(true)) + { + if (GetGameObjectPath(t.gameObject) == s) return t.gameObject; + } + return null; + } + return GameObject.Find(s); + } + catch { } }
Code ReviewOverall, this is a solid PR that addresses issue #547 comprehensively. The changes add Prefab Stage support while also improving inactive object handling. However, there are a few outstanding issues from other reviewers that should be addressed before merging: ✅ Strengths
|
Summary
Fixes #547
When a prefab is opened in Unity's Prefab Stage (isolation editing mode),
find_gameobjectsand related tools now correctly find GameObjects within the prefab.Changes
GameObjectLookup.cs: Modified
GetAllSceneObjects()to check for Prefab Stage first usingPrefabStageUtility.GetCurrentPrefabStage(). When in prefab editing mode, returns objects from the prefab contents root instead of the main scene.ManageGameObjectCommon.cs: Updated
SearchByPath()to handle Prefab Stage - usesprefabContentsRoot.transform.Find()instead ofGameObject.Find()which doesn't work in Prefab Stage.ManageScene.cs: Updated
GetHierarchy()to return the prefab hierarchy when in Prefab Stage mode.Testing
find_gameobjectsreturns correct results🤖 Generated with Claude Code
Summary by Sourcery
Add support for Unity Prefab Stage when querying and managing GameObjects and scene hierarchy.
Bug Fixes:
Enhancements:
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.