Files
Tomicz Engineering LLC deea7d2a56 Replace reflection with version-gated conditional compilation.
Addresses review feedback on the Unity 6.5 GetInstanceID migration:

- UnityObjectIdCompatExtensions: drop the reflective method lookup in
  favor of a simple #if UNITY_6000_5_OR_NEWER / #else split calling
  GetEntityId() or GetInstanceID() directly. Also wrap the class in
  the MCPForUnity.Runtime.Helpers namespace.
- UnityTypeConverters: remove the reflective EntityIdToObject probe and
  call EditorUtility.EntityIdToObject(EntityId) directly under the same
  version gate. Serialize entityID as EntityId.ToULong() rather than
  ToString(), since Unity's docs explicitly warn that the textual form
  is not a stable serialization contract.
- Drop #pragma warning disable 0619 from 22 files that no longer make
  any direct calls to obsolete APIs. The remaining 7 files still need
  it (FindObjectsOfType, InstanceIDToObject fallback) and are left as-is
  — those deprecations are out of scope for this PR.
- Add the MCPForUnity.Runtime.Helpers using to every file that calls
  GetInstanceIDCompat() now that the extension method lives in a
  namespace.
2026-04-11 22:55:45 +02:00

88 lines
3.2 KiB
C#

#nullable disable
using MCPForUnity.Editor.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using MCPForUnity.Runtime.Helpers;
namespace MCPForUnity.Editor.Tools.GameObjects
{
internal static class GameObjectDuplicate
{
internal static object Handle(JObject @params, JToken targetToken, string searchMethod)
{
GameObject sourceGo = ManageGameObjectCommon.FindObjectInternal(targetToken, searchMethod);
if (sourceGo == null)
{
return new ErrorResponse($"Target GameObject ('{targetToken}') not found using method '{searchMethod ?? "default"}'.");
}
string newName = @params["new_name"]?.ToString();
Vector3? position = VectorParsing.ParseVector3(@params["position"]);
Vector3? offset = VectorParsing.ParseVector3(@params["offset"]);
JToken parentToken = @params["parent"];
GameObject duplicatedGo = UnityEngine.Object.Instantiate(sourceGo);
Undo.RegisterCreatedObjectUndo(duplicatedGo, $"Duplicate {sourceGo.name}");
if (!string.IsNullOrEmpty(newName))
{
duplicatedGo.name = newName;
}
else
{
duplicatedGo.name = sourceGo.name.Replace("(Clone)", "").Trim() + "_Copy";
}
if (position.HasValue)
{
duplicatedGo.transform.position = position.Value;
}
else if (offset.HasValue)
{
duplicatedGo.transform.position = sourceGo.transform.position + offset.Value;
}
if (parentToken != null)
{
if (parentToken.Type == JTokenType.Null || (parentToken.Type == JTokenType.String && string.IsNullOrEmpty(parentToken.ToString())))
{
duplicatedGo.transform.SetParent(null);
}
else
{
GameObject newParent = ManageGameObjectCommon.FindObjectInternal(parentToken, "by_id_or_name_or_path");
if (newParent != null)
{
duplicatedGo.transform.SetParent(newParent.transform, true);
}
else
{
McpLog.Warn($"[ManageGameObject.Duplicate] Parent '{parentToken}' not found. Object will remain at root level.");
}
}
}
else
{
duplicatedGo.transform.SetParent(sourceGo.transform.parent, true);
}
EditorUtility.SetDirty(duplicatedGo);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
Selection.activeGameObject = duplicatedGo;
return new SuccessResponse(
$"Duplicated '{sourceGo.name}' as '{duplicatedGo.name}'.",
new
{
originalName = sourceGo.name,
originalId = sourceGo.GetInstanceIDCompat(),
duplicatedObject = Helpers.GameObjectSerializer.GetGameObjectData(duplicatedGo)
}
);
}
}
}