Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -181,27 +181,37 @@ 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();

// 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;
}
Comment on lines -184 to 215

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.


~BufferedFileLogStorage() => Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,74 @@
/*
┌──────────────────────────────────────────────────────────────────┐
│ 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.
*/
Comment on lines +2 to +7

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


#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
{
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)

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.

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;
Comment on lines +11 to 74

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

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*/
Comment on lines +2 to +7

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


#nullable enable
#if UNITY_EDITOR && !UNITY_6000_5_OR_NEWER
using System.Linq;
using com.IvanMurzak.McpPlugin.Common;
using UnityEngine;
using UnityEngine.SceneManagement;
Expand All @@ -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>
Expand All @@ -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);

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.

var obj = UnityEditor.EditorUtility.EntityIdToObject((EntityId)instanceID);
#else
var obj = UnityEditor.EditorUtility.InstanceIDToObject(instanceID);
#endif
Comment on lines 8 to 74

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

Expand Down