From 248c9613eeffa015f4fa980e9328fd5937d3f9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=A5=E6=97=A5=E9=87=8E=E6=82=A0?= <870042881@qq.com> Date: Mon, 15 Jun 2026 18:39:23 +0800 Subject: [PATCH 1/2] fix: include DontDestroyOnLoad objects in gameobject-find search scope 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) --- .../Runtime/Utils/GameObjectUtils.Editor.cs | 55 +++++++++++++------ .../GameObjectUtils.Editor.pre-Unity.6.5.cs | 48 +++++++++++----- 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.cs b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.cs index 483b059d9..4ce1746a9 100644 --- a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.cs +++ b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.cs @@ -1,16 +1,16 @@ /* -┌──────────────────────────────────────────────────────────────────┐ -│ 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. │ -└──────────────────────────────────────────────────────────────────┘ -*/ + * 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. + */ #nullable enable #if UNITY_EDITOR && UNITY_6000_5_OR_NEWER +using System.Linq; using com.IvanMurzak.McpPlugin.Common; +using UnityEngine; using UnityEngine.SceneManagement; namespace com.IvanMurzak.Unity.MCP.Runtime.Utils @@ -18,36 +18,57 @@ namespace com.IvanMurzak.Unity.MCP.Runtime.Utils public static partial class GameObjectUtils { /// - /// Find Root GameObject in opened Prefab. Of array of GameObjects in a scene. + /// Find Root GameObject in opened Prefab, active scene, and DontDestroyOnLoad. /// /// Scene for the search, if null the current active scene would be used /// Array of root GameObjects - public static UnityEngine.GameObject[] FindRootGameObjects(Scene? scene = null) + public static GameObject[] FindRootGameObjects(Scene? scene = null) { var prefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage(); 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() + .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 UnityEngine.GameObject? FindByInstanceID(UnityEngine.EntityId instanceID) + + public static GameObject? FindByInstanceID(EntityId instanceID) { - 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) return null; return go; diff --git a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.pre-Unity.6.5.cs b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.pre-Unity.6.5.cs index 0d405b0db..d13114822 100644 --- a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.pre-Unity.6.5.cs +++ b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Utils/GameObjectUtils.Editor.pre-Unity.6.5.cs @@ -1,15 +1,14 @@ /* -┌──────────────────────────────────────────────────────────────────┐ -│ 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. │ -└──────────────────────────────────────────────────────────────────┘ -*/ + * 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. + */ #nullable enable #if UNITY_EDITOR && !UNITY_6000_5_OR_NEWER +using System.Linq; using com.IvanMurzak.McpPlugin.Common; using UnityEngine; using UnityEngine.SceneManagement; @@ -19,7 +18,7 @@ namespace com.IvanMurzak.Unity.MCP.Runtime.Utils public static partial class GameObjectUtils { /// - /// Find Root GameObject in opened Prefab. Of array of GameObjects in a scene. + /// Find Root GameObject in opened Prefab, active scene, and DontDestroyOnLoad. /// /// Scene for the search, if null the current active scene would be used /// Array of root GameObjects @@ -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() + .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 From 35548c5ff3f4fe4009e68a18e42fb26871e396bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=83=E5=B1=B1=E4=B8=87=E6=B0=B4=E6=88=91=E9=99=AA?= =?UTF-8?q?=E4=BD=A0=E7=9C=8B?= <870042881@qq.com> Date: Fri, 19 Jun 2026 03:30:52 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E3=80=90AI=E3=80=91fix:=20includeStackTrac?= =?UTF-8?q?e=3Dfalse=20=E6=9C=AA=E7=94=9F=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 FileLogStorage.QueryInternal() 中 includeStackTrace 参数未被使用的问题 - 修复 BufferedFileLogStorage.QueryInternal() 中多个返回点未清除 StackTrace 的问题 - 添加 ClearStackTraceIfNeeded() 辅助方法确保行为一致 当 includeStackTrace 为 false 时,返回的 LogEntry 中 StackTrace 属性现在会被正确清除为 null --- .../Unity/Logs/BufferedFileLogStorage.cs | 18 ++++++++++++++---- .../Runtime/Unity/Logs/FileLogStorage.cs | 7 +++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/BufferedFileLogStorage.cs b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/BufferedFileLogStorage.cs index 514bc9fa0..838dca1de 100644 --- a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/BufferedFileLogStorage.cs +++ b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/BufferedFileLogStorage.cs @@ -181,19 +181,19 @@ protected override LogEntry[] QueryInternal( { if (entry.Timestamp < cutoffTime) { - return result.AsEnumerable().Reverse().ToArray(); + return ClearStackTraceIfNeeded(result.AsEnumerable().Reverse().ToArray(), includeStackTrace); } } result.Add(entry); if (result.Count >= maxEntries) - return result.AsEnumerable().Reverse().ToArray(); + return ClearStackTraceIfNeeded(result.AsEnumerable().Reverse().ToArray(), includeStackTrace); } // 2. Exit if we already have enough entries var neededLogsCount = maxEntries - result.Count; if (neededLogsCount <= 0) - return result.AsEnumerable().Reverse().ToArray(); + return ClearStackTraceIfNeeded(result.AsEnumerable().Reverse().ToArray(), includeStackTrace); result.Reverse(); @@ -201,7 +201,17 @@ protected override LogEntry[] QueryInternal( var fileEntries = base.QueryInternal(neededLogsCount, logTypeFilter, includeStackTrace, lastMinutes); result.AddRange(fileEntries); - return result.ToArray(); + return ClearStackTraceIfNeeded(result.ToArray(), includeStackTrace); + } + + private static LogEntry[] ClearStackTraceIfNeeded(LogEntry[] entries, bool includeStackTrace) + { + if (!includeStackTrace) + { + foreach (var log in entries) + log.StackTrace = null; + } + return entries; } ~BufferedFileLogStorage() => Dispose(); diff --git a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/FileLogStorage.cs b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/FileLogStorage.cs index 68caf8192..cd948525e 100644 --- a/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/FileLogStorage.cs +++ b/Unity-MCP-Plugin/Packages/com.ivanmurzak.unity.mcp/Runtime/Unity/Logs/FileLogStorage.cs @@ -341,6 +341,13 @@ protected virtual LogEntry[] QueryInternal( .Reverse() .ToArray(); + // Clear stack traces if not requested + if (!includeStackTrace) + { + foreach (var log in filteredLogs) + log.StackTrace = null; + } + return filteredLogs; } }