Unity undo

Unity – Undo Redo in Editor

On Unity and in almost all other software, you use “CTRL + Z” or “Command + Z” to undo and “CTRL + Y” or “Command + Y” to redo an action.

However, when using a custom script in the editor, undo action must be implemented.
Otherwise, no matter how hard you hammer your keys, nothing will happen.

It is very important to specify these methods, as a bad click happens so quickly and without the possibility of undo, it can be dramatic.

Implementing undo in an editor script

Undo is a static C# class, and various methods must be used depending on the actions you perform.
Undo methods all have a string parameter, which is used to name the action performed.

You can then find it in the editor at the top of the ‘Edit‘ menu.

Unity show menu edit with undo label

Modifying a gameObject

To modify a gameObject, use Undo.RecordObject.
Be careful to pass the component you are modifying as a parameter, eg :

  • If you modify the name of a gameObject, the gameObject must be passed as a parameter.
  • If you are modifying the position of the gameObject, the transform component must be the parameter.
[MenuItem("Window/Reset Position")]
public static void Reset()
{
	var go = Selection.activeGameObject;
	Undo.RecordObject(go.transform, "reset position");

	go.transform.position = Vector3.zero;
}

Adding a component

To cancel the addition of a component, the method is different: you no longer need to use AddComponent.
Replace it with Undo.AddComponent.

[MenuItem("Window/Add BoxCollider")]
public static void AddBoxCollider()
{
	var go = Selection.activeGameObject;
	Undo.AddComponent<BoxCollider>(go);
}

Destroy GameObject

In the editor, we usually use Object.DestroyImmediate to destroy a GameObject.
For an undo action, use Undo.DestroyObjectImmediate instead.
This function should also be used to destroy a component.

var go = Selection.activeGameObject;
Undo.DestroyObjectImmediate(go);

Create GameObject

To create or instantiate a gameObject, Undo.RegisterCreatedObjectUndo must be called to register the Undo action.

[MenuItem("Window/Add Cube")]
public static void AddCube()
{
	var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
	Undo.RegisterCreatedObjectUndo(cube, "Add Cube");
}

Modifying the hierarchy

When modifying the hierarchy to record an undo action, use Undo.SetTransformParent to change the parent.
For positional modifications use Undo.SetSiblingIndex.

var go = Selection.activeGameObject;
Undo.SetTransformParent(go.transform, parentTransform, "Set parent");
Undo.SetSiblingIndex(go.transform, 0, "Set on top");

So here are the most commonly used functions for recording Undo.

Bulk Undo

You can also save undos in groups, so you can perform a multitude of actions and undo them all at once.
Very useful if you don’t want to spam “CTRL + Z” for 2 hours …

  1. You’ll need to use the Undo.SetCurrentGroupName method to name your group.
  2. Then retrieve the group id using Undo.GetCurrentGroup.
  3. And then merge it all together using Undo.CollapseUndoOperations.
[MenuItem("Window/ResetDisable")]
public static void ResetDeactivate()
{
	// set group
	Undo.SetCurrentGroupName("Reset & Disable GameObject");

	// get current group
	int group = Undo.GetCurrentGroup();

	var go = Selection.activeGameObject;
	Undo.RecordObject(go.transform, "Reset position");

	go.transform.position = Vector3.zero;

	Undo.RecordObject(go, "Disable GameObject");

	go.SetActive(false);

	// merge all undo in the group
	Undo.CollapseUndoOperations(group);
}

In conclusion, remember to implement your Undo when working with scripts in the editor.
It will save you a lot of time and help you complete your project.

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *