fix: include DontDestroyOnLoad objects in gameobject-find search scope#827
fix: include DontDestroyOnLoad objects in gameobject-find search scope#827kisszuopumingdao wants to merge 1 commit into
Conversation
When searching by name or path, FindRootGameObjects() only returned active scene root objects. Games using DontDestroyOnLoad for UI canvases could not be found by gameobject-find. Now includes DontDestroyOnLoad root objects when in Play mode. Co-authored-by: AI (Codex) <noreply@openai.com>
IvanMurzak
left a comment
There was a problem hiding this comment.
Probably low quality AI model was used. This pull request brings more issues than fixes.
| #if UNITY_EDITOR && UNITY_6000_5_OR_NEWER | ||
| using System.Linq; | ||
| using com.IvanMurzak.McpPlugin.Common; | ||
| using UnityEngine; |
There was a problem hiding this comment.
Do not add UnityEngine here. The idea to keep each line in the file with the full explicit type name <namespace>.<className> to prevent name conflicts and to simplify support of multiple different Unity versions with different namespaces per the same class name.
| ┌──────────────────────────────────────────────────────────────────┐ | ||
| │ Author: Ivan Murzak (https://github.com/IvanMurzak) │ | ||
| │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │ | ||
| │ Copyright (c) 2025 Ivan Murzak │ | ||
| │ Licensed under the Apache License, Version 2.0. │ | ||
| │ See the LICENSE file in the project root for more information. │ |
| if (instanceID == UnityEngine.EntityId.None) | ||
| if (instanceID == EntityId.None) | ||
| return null; | ||
|
|
||
| var obj = UnityEditor.EditorUtility.EntityIdToObject(instanceID); | ||
| if (obj is not UnityEngine.GameObject go) | ||
| if (obj is not GameObject go) |
There was a problem hiding this comment.
Need to keep using the full explicit class <namespace>.<className>
| // Include DontDestroyOnLoad root objects (only available at runtime) | ||
| if (UnityEditor.EditorApplication.isPlaying) | ||
| { | ||
| var ddolRoots = Resources.FindObjectsOfTypeAll<GameObject>() |
There was a problem hiding this comment.
This is way too heavy operation Resources.FindObjectsOfTypeAll. We can't use it.
| var combined = new GameObject[rootGos.Length + ddolRoots.Length]; | ||
| rootGos.CopyTo(combined, 0); | ||
| ddolRoots.CopyTo(combined, rootGos.Length); | ||
| return combined; |
There was a problem hiding this comment.
Instead making low level array operations need to utilize IEnumerable and LINQ to prevent emitting garbage memory for temporary arrays.
| @@ -19,7 +18,7 @@ namespace com.IvanMurzak.Unity.MCP.Runtime.Utils | |||
| public static partial class GameObjectUtils | |||
| { | |||
| /// <summary> | |||
| /// Find Root GameObject in opened Prefab. Of array of GameObjects in a scene. | |||
| /// Find Root GameObject in opened Prefab, active scene, and DontDestroyOnLoad. | |||
| /// </summary> | |||
| /// <param name="scene">Scene for the search, if null the current active scene would be used</param> | |||
| /// <returns>Array of root GameObjects</returns> | |||
| @@ -29,26 +28,47 @@ public static GameObject[] FindRootGameObjects(Scene? scene = null) | |||
| if (prefabStage != null) | |||
| return prefabStage.prefabContentsRoot.MakeArray(); | |||
|
|
|||
| GameObject[] rootGos; | |||
|
|
|||
| if (scene == null) | |||
| { | |||
| var rootGos = UnityEditor.SceneManagement.EditorSceneManager | |||
| rootGos = UnityEditor.SceneManagement.EditorSceneManager | |||
| .GetActiveScene() | |||
| .GetRootGameObjects(); | |||
|
|
|||
| return rootGos; | |||
| } | |||
| else | |||
| { | |||
| return scene.Value.GetRootGameObjects(); | |||
| rootGos = scene.Value.GetRootGameObjects(); | |||
| } | |||
|
|
|||
| // Include DontDestroyOnLoad root objects (only available at runtime) | |||
| if (UnityEditor.EditorApplication.isPlaying) | |||
| { | |||
| var ddolRoots = Resources.FindObjectsOfTypeAll<GameObject>() | |||
| .Where(go => go.scene.name == "DontDestroyOnLoad" | |||
| && go.transform.parent == null | |||
| && (go.hideFlags == HideFlags.None || go.hideFlags == HideFlags.HideInHierarchy)) | |||
| .ToArray(); | |||
|
|
|||
| if (ddolRoots.Length > 0) | |||
| { | |||
| var combined = new GameObject[rootGos.Length + ddolRoots.Length]; | |||
| rootGos.CopyTo(combined, 0); | |||
| ddolRoots.CopyTo(combined, rootGos.Length); | |||
| return combined; | |||
| } | |||
| } | |||
|
|
|||
| return rootGos; | |||
| } | |||
|
|
|||
| public static GameObject? FindByInstanceID(int instanceID) | |||
| { | |||
| if (instanceID == 0) | |||
| return null; | |||
|
|
|||
| #if UNITY_6000_3_OR_NEWER | |||
| var obj = UnityEditor.EditorUtility.EntityIdToObject((UnityEngine.EntityId)instanceID); | |||
| var obj = UnityEditor.EditorUtility.EntityIdToObject((EntityId)instanceID); | |||
| #else | |||
| var obj = UnityEditor.EditorUtility.InstanceIDToObject(instanceID); | |||
| #endif | |||
There was a problem hiding this comment.
Same issues as in the GameObjectUtils.Editor.cs file
What changed
Added DontDestroyOnLoad scene root objects to the
gameobject-findsearch scope inFindRootGameObjects().Why
Many games use
DontDestroyOnLoadto keep UI canvases alive across scene transitions. The existingFindRootGameObjects()only searched the active scene's root objects viaEditorSceneManager.GetActiveScene().GetRootGameObjects(), which returned 0 results when all UI was in DontDestroyOnLoad.This caused
gameobject-findto fail with "Not found GameObject with name 'X'" even though the objects existed and were findable viaGameObject.Find().Root cause
GameObjectUtils.Editor.cs—FindRootGameObjects()only returned active scene roots. Objects in DontDestroyOnLoad were invisible to the search.Fix
When in Play mode, additionally search DontDestroyOnLoad root objects using
Resources.FindObjectsOfTypeAlland combine them with the active scene roots.Verification
Tested in a Unity project where all UI canvases use DontDestroyOnLoad:
gameobject-findwith name "BtnClose" → "Not found"gameobject-findwith name "BtnClose" → found (sceneName: "DontDestroyOnLoad")Files changed
GameObjectUtils.Editor.cs(Unity 6.5+)GameObjectUtils.Editor.pre-Unity.6.5.cs(pre-Unity 6.5)Co-authored-by: AI (Codex) noreply@openai.com