From 99738559c02a5e8a030ecb29e7ffa784f21f867b Mon Sep 17 00:00:00 2001 From: Dallon Date: Mon, 18 May 2026 16:25:26 -0700 Subject: [PATCH] fix: register undo when deleting GameObjects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit manage_gameobject(action="delete") called Object.DestroyImmediate directly, bypassing Unity's undo stack — manage_editor(action="undo") could not recover deleted objects. Switching to Undo.DestroyObjectImmediate restores the expected editor-undo behavior with full reference-graph restoration. The package already uses Undo.DestroyObjectImmediate correctly elsewhere (ComponentOps.cs, GameObjectComponentHelpers.cs); GameObjectDelete.cs was the outlier. The stale TODO/comment about "Unity 2022+" is from the 2021.3 era — Undo.DestroyObjectImmediate has been stable across all currently-supported Unity versions. Adds Delete_RegistersUndo_RestoresOnUndo test (delete then undo, assert restoration) to the existing ManageGameObjectDeleteTests baseline. --- .../Tools/GameObjects/GameObjectDelete.cs | 5 +--- .../Tools/ManageGameObjectDeleteTests.cs | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs b/MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs index 74382ef49..74d573ab8 100644 --- a/MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs +++ b/MCPForUnity/Editor/Tools/GameObjects/GameObjectDelete.cs @@ -26,10 +26,7 @@ internal static object Handle(JToken targetToken, string searchMethod) { string goName = targetGo.name; int goId = targetGo.GetInstanceIDCompat(); - // Note: Undo.DestroyObjectImmediate doesn't work reliably in test context, - // so we use Object.DestroyImmediate. This means delete isn't undoable. - // TODO: Investigate Undo.DestroyObjectImmediate behavior in Unity 2022+ - Object.DestroyImmediate(targetGo); + Undo.DestroyObjectImmediate(targetGo); deletedObjects.Add(new { name = goName, instanceID = goId }); } } diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectDeleteTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectDeleteTests.cs index f3afc7d35..e3e03655b 100644 --- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectDeleteTests.cs +++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageGameObjectDeleteTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using NUnit.Framework; +using UnityEditor; using UnityEngine; using Newtonsoft.Json.Linq; using MCPForUnity.Editor.Tools.GameObjects; @@ -375,6 +376,35 @@ public void Delete_MultipleObjectsSameName_DeletesCorrectly() } #endregion + + #region Undo Tests + + [Test] + public void Delete_RegistersUndo_RestoresOnUndo() + { + var target = CreateTestObject("UndoRoundtrip"); + + var p = new JObject + { + ["action"] = "delete", + ["target"] = "UndoRoundtrip", + ["searchMethod"] = "by_name" + }; + + var result = ManageGameObject.HandleCommand(p); + var resultObj = result as JObject ?? JObject.FromObject(result); + Assert.IsTrue(resultObj.Value("success"), resultObj.ToString()); + Assert.IsNull(GameObject.Find("UndoRoundtrip"), "Object should be deleted before undo"); + testObjects.Remove(target); + + Undo.PerformUndo(); + + var restored = GameObject.Find("UndoRoundtrip"); + Assert.IsNotNull(restored, "Undo should restore deleted GameObject"); + testObjects.Add(restored); + } + + #endregion } }