Skip to content

fix: [AI] includeStackTrace not working & DontDestroyOnLoad objects missing in gameobject-find#836

Open
kisszuopumingdao wants to merge 4 commits into
IvanMurzak:mainfrom
kisszuopumingdao:fix/console-get-logs-stacktrace
Open

fix: [AI] includeStackTrace not working & DontDestroyOnLoad objects missing in gameobject-find#836
kisszuopumingdao wants to merge 4 commits into
IvanMurzak:mainfrom
kisszuopumingdao:fix/console-get-logs-stacktrace

Conversation

@kisszuopumingdao

@kisszuopumingdao kisszuopumingdao commented Jun 18, 2026

Copy link
Copy Markdown

Changes

1. Fix includeStackTrace=false not working in console-get-logs

Problem: The includeStackTrace parameter in the console-get-logs tool does not work when set to false. Log
entries still contain StackTrace information even when explicitly disabled.

Root Cause: The includeStackTrace parameter is passed through the entire call chain but never actually used to
filter out the StackTrace property:

  • FileLogStorage.QueryInternal() receives the parameter but never uses it
  • BufferedFileLogStorage.QueryInternal() has multiple return points that don't handle the parameter

Fix:

  • Fix FileLogStorage.QueryInternal() to clear StackTrace based on includeStackTrace before returning results
  • Fix BufferedFileLogStorage.QueryInternal() to handle includeStackTrace at all return points
  • Add ClearStackTraceIfNeeded() helper method to ensure consistent behavior

2. Fix DontDestroyOnLoad objects missing in gameobject-find search scope

Problem: 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.

Fix: Now includes DontDestroyOnLoad root objects when in Play mode.

Testing

console-get-logs

  • includeStackTrace: falseStackTrace is null
  • includeStackTrace: trueStackTrace contains stack trace information

gameobject-find

  • Objects marked with DontDestroyOnLoad are now discoverable when searching in Play mode

kisszuopumingdao and others added 2 commits June 15, 2026 18:39
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>
- 修复 FileLogStorage.QueryInternal() 中 includeStackTrace 参数未被使用的问题
- 修复 BufferedFileLogStorage.QueryInternal() 中多个返回点未清除 StackTrace 的问题
- 添加 ClearStackTraceIfNeeded() 辅助方法确保行为一致

当 includeStackTrace 为 false 时,返回的 LogEntry 中 StackTrace 属性现在会被正确清除为 null
@kisszuopumingdao kisszuopumingdao changed the title 【AI】fix: includeStackTrace=false not working in console-get-logs 【AI】fix: 1.includeStackTrace=false not working in console-get-logs 2.include DontDestroyOnLoad objects in gameobject-find search scope Jun 18, 2026
@kisszuopumingdao kisszuopumingdao changed the title 【AI】fix: 1.includeStackTrace=false not working in console-get-logs 2.include DontDestroyOnLoad objects in gameobject-find search scope 【AI】fix: includeStackTrace not working & DontDestroyOnLoad objects missing in gameobject-find Jun 18, 2026
@kisszuopumingdao kisszuopumingdao changed the title 【AI】fix: includeStackTrace not working & DontDestroyOnLoad objects missing in gameobject-find fix: [AI] includeStackTrace not working & DontDestroyOnLoad objects missing in gameobject-find Jun 18, 2026

@IvanMurzak IvanMurzak left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Probably weak AI model was used. This pull request has low quality.

Comment on lines +2 to +7
* 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.
*/

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Incorrect header style

Comment on lines +2 to +7
* 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.
*/

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Incorrect header style

Comment on lines +11 to 74
using System.Linq;
using com.IvanMurzak.McpPlugin.Common;
using UnityEngine;
using UnityEngine.SceneManagement;

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>
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<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 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;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

GameObject logic should not be included in the PR about logs stacktrace

Comment on lines 8 to 74
@@ -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

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

GameObject logic should not be included in the PR about logs stacktrace

return null;

#if UNITY_6000_3_OR_NEWER
var obj = UnityEditor.EditorUtility.EntityIdToObject((UnityEngine.EntityId)instanceID);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

UnityEngine namespace should be explicitly set in each line where a type is used.


public static GameObject? FindByInstanceID(EntityId instanceID)
{
if (instanceID == UnityEngine.EntityId.None)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

UnityEngine namespace should be explicitly set in each line where a type is used.

Comment on lines -184 to 215
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();

// 3. Get from file
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;
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This implementation has a weak quality, because it creates an array and then tries to modify after creation. It would be more efficient to use LINQ to generate the proper data using a proper query.

And ideally need to minimize the amount of places where this should be applied to 1, if that is possible.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

   12 files    624 suites   49m 35s ⏱️
  892 tests   890 ✅ 1 💤 1 ❌
5 352 runs  5 340 ✅ 6 💤 6 ❌

For more details on these failures, see this check.

Results for commit 35548c5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants