diff --git a/UnityMcpBridge/Editor/Helpers/GameObjectSerializer.cs b/UnityMcpBridge/Editor/Helpers/GameObjectSerializer.cs
new file mode 100644
index 0000000..51f6d97
--- /dev/null
+++ b/UnityMcpBridge/Editor/Helpers/GameObjectSerializer.cs
@@ -0,0 +1,527 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using UnityEditor;
+using UnityEngine;
+using UnityMcpBridge.Runtime.Serialization; // For Converters
+
+namespace UnityMcpBridge.Editor.Helpers
+{
+ ///
+ /// Handles serialization of GameObjects and Components for MCP responses.
+ /// Includes reflection helpers and caching for performance.
+ /// tew
+ public static class GameObjectSerializer
+ {
+ // --- Data Serialization ---
+
+ ///
+ /// Creates a serializable representation of a GameObject.
+ ///
+ public static object GetGameObjectData(GameObject go)
+ {
+ if (go == null)
+ return null;
+ return new
+ {
+ name = go.name,
+ instanceID = go.GetInstanceID(),
+ tag = go.tag,
+ layer = go.layer,
+ activeSelf = go.activeSelf,
+ activeInHierarchy = go.activeInHierarchy,
+ isStatic = go.isStatic,
+ scenePath = go.scene.path, // Identify which scene it belongs to
+ transform = new // Serialize transform components carefully to avoid JSON issues
+ {
+ // Serialize Vector3 components individually to prevent self-referencing loops.
+ // The default serializer can struggle with properties like Vector3.normalized.
+ position = new
+ {
+ x = go.transform.position.x,
+ y = go.transform.position.y,
+ z = go.transform.position.z,
+ },
+ localPosition = new
+ {
+ x = go.transform.localPosition.x,
+ y = go.transform.localPosition.y,
+ z = go.transform.localPosition.z,
+ },
+ rotation = new
+ {
+ x = go.transform.rotation.eulerAngles.x,
+ y = go.transform.rotation.eulerAngles.y,
+ z = go.transform.rotation.eulerAngles.z,
+ },
+ localRotation = new
+ {
+ x = go.transform.localRotation.eulerAngles.x,
+ y = go.transform.localRotation.eulerAngles.y,
+ z = go.transform.localRotation.eulerAngles.z,
+ },
+ scale = new
+ {
+ x = go.transform.localScale.x,
+ y = go.transform.localScale.y,
+ z = go.transform.localScale.z,
+ },
+ forward = new
+ {
+ x = go.transform.forward.x,
+ y = go.transform.forward.y,
+ z = go.transform.forward.z,
+ },
+ up = new
+ {
+ x = go.transform.up.x,
+ y = go.transform.up.y,
+ z = go.transform.up.z,
+ },
+ right = new
+ {
+ x = go.transform.right.x,
+ y = go.transform.right.y,
+ z = go.transform.right.z,
+ },
+ },
+ parentInstanceID = go.transform.parent?.gameObject.GetInstanceID() ?? 0, // 0 if no parent
+ // Optionally include components, but can be large
+ // components = go.GetComponents().Select(c => GetComponentData(c)).ToList()
+ // Or just component names:
+ componentNames = go.GetComponents()
+ .Select(c => c.GetType().FullName)
+ .ToList(),
+ };
+ }
+
+ // --- Metadata Caching for Reflection ---
+ private class CachedMetadata
+ {
+ public readonly List SerializableProperties;
+ public readonly List SerializableFields;
+
+ public CachedMetadata(List properties, List fields)
+ {
+ SerializableProperties = properties;
+ SerializableFields = fields;
+ }
+ }
+ // Key becomes Tuple
+ private static readonly Dictionary, CachedMetadata> _metadataCache = new Dictionary, CachedMetadata>();
+ // --- End Metadata Caching ---
+
+ ///
+ /// Creates a serializable representation of a Component, attempting to serialize
+ /// public properties and fields using reflection, with caching and control over non-public fields.
+ ///
+ // Add the flag parameter here
+ public static object GetComponentData(Component c, bool includeNonPublicSerializedFields = true)
+ {
+ // --- Add Early Logging ---
+ // Debug.Log($"[GetComponentData] Starting for component: {c?.GetType()?.FullName ?? "null"} (ID: {c?.GetInstanceID() ?? 0})");
+ // --- End Early Logging ---
+
+ if (c == null) return null;
+ Type componentType = c.GetType();
+
+ // --- Special handling for Transform to avoid reflection crashes and problematic properties ---
+ if (componentType == typeof(Transform))
+ {
+ Transform tr = c as Transform;
+ // Debug.Log($"[GetComponentData] Manually serializing Transform (ID: {tr.GetInstanceID()})");
+ return new Dictionary
+ {
+ { "typeName", componentType.FullName },
+ { "instanceID", tr.GetInstanceID() },
+ // Manually extract known-safe properties. Avoid Quaternion 'rotation' and 'lossyScale'.
+ { "position", CreateTokenFromValue(tr.position, typeof(Vector3))?.ToObject