How to replace SetDirty with Undo.RecordObject?

In my editor script, I use EditorUtility.SetDirty to mark the scene as dirty when my custom inspector button is pressed. It works, but the changes aren’t recorded on the undo stack. I’ve heard that Undo.RecordObject can replace SetDirty for this purpose, but I don’t know how to use it. This is my original code:

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(CharacterFlipper))]
public class CharacterFlipperEditor : Editor
{
    private CharacterFlipper _characterFlipper;

    private void OnEnable()
    {
        _characterFlipper = (CharacterFlipper) target;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (GUILayout.Button("Flip"))
        {
            _characterFlipper.Flip();
             EditorUtility.SetDirty(target);
        }
    }
   
}

How would I use Undo.RecordObject to record the changes? Simply replacing SetDirty with it doesn’t work.

There used to be an example in the docs for record object… is it no longer there?

That example uses OnSceneGUI rather than checking if a button is pressed in the inspector. I don’t know how to apply it to my case.

So you have a thing.

You’re gonna change that thing, somehow.

Whatever that thing is, it doesn’t matter.

You want to preserve a snapshot of that thing the way it is before you change it.

Undo.RecordObject() is used to take a snapshot of that thing before you change it, as the API example code shows.

Figure out what that thing (or things) is, and undo recordobject them (or recordobjects).

If your flip() function is a helper that manipulates other stuff, perhaps put the undo record inside there, but it is an editor-only thing, so perhaps outside is appropriate.

Either way, you need to give the thing or things you’re contemplating changing to the undo record API.

1 Like

I don’t know where to put the line Undo.RecordObject(target, "Character Flip"); in my script. No matter where I put it, it doesn’t record the change. The flip function multiplies transform.localScale.x by -1.

You need to record the Undo on the object that will change. If your method changes the localScale of the transform, you need to record the undo on the transform, not the CharacterFlipper.

Also, in terms of general architecture with Undo.RecordChange, the call needs to occur before the change. SetDirty happens after.

3 Likes

This ^ ^ ^

That did it. I just needed to write Undo.RecordObject(_characterFlipper.transform, "Character Flip"); before calling the Flip function. Thank you so much :slight_smile:

1 Like