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.
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 …
- You’ll need to use the
Undo.SetCurrentGroupName
method to name your group. - Then retrieve the group id using
Undo.GetCurrentGroup
. - 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.