What is the correct usage of RegisterCompleteObjectUndo/RegisterFullObjectHierarchyUndo

After upgrading to Unity4, and going through to tweak the usages of RegisterUndo, I note that a couple of extra functions are present in the Undo namespace, with little or no documentation. Specifically RegisterFullObjectHierarchyUndo and RegisterCompleteObjectUndo.

Previously, I’d used RegisterSceneUndo, despite the obvious performance concerns, because it was the best compromise between succinctness in the code and effectiveness. I’m not writing code for a plugin or for sale, this is all just helper code for my own project. RegisterUndo (now RecordObject), as far as I can tell, works on a single Component only. Most of my operations start at a parent GameObject/Component and make changes to children, and cross-linked Components. But unless I put in a RecordObject call for every single Component I touch, this is rather unwieldy. What I’d like to do is put a simple bit of Editor/Undo stuff at the top of the function (with similar SetDirty calls at the button of the function), that records the state of all of the objects I might touch, even if they don’t actually get changed. The reason for this is because I have complex iterations / conditionals that mean that I don’t know what objects are actually going to be touched by the call, other than that they’re all underneath the root object that starts the operation. I’m stuck between having the same conditional logic in two places (and getting out of sync as development continues), or littering a function with Undo.RecordObject calls at the point at which I make a change. That starts to decay as well if I make multiple separate changes to a single component in different places. I have to record the object multiple times at each point of change, just in case the other conditional change didn’t get hit.

I got around this before by the brute force method of RegisterSceneUndo, but that is now deprecated. RegisterFullObjectHierarchyUndo and RegisterCompleteObjectUndo tease us with their names, implying that a single call with a root component / object will preserve the state of more than just a single component. But the documentation on them is poor: RegisterCompleteObjectUndo’s documentation is empty, but the function is referred to in ClearUndo (‘Removes aall[sic] Undo operation for the identifier object registered using Undo.RegisterCompleteObjectUndo from the undo stack.’) - and doesn’t sound like it does what its name would suggest. I would expect RegisterCompleteObjectUndo to call RecordObject on every component on a GameObject. RegisterFullObjectHierarchyUndo seems even more apt; I’d presume that it takes an Object and calls RecordObject on every component / object on all the children of that object. That would be ideal - 90% of my functions modify only an object and its children.

Are these functions supported, or even properly functional? Does anyone have some solid test cases to show what they do and do not do?

The Unity documentation has been updated since:

Undo.RegisterCompleteObjectUndo(Object objectToUndo, string name) will record a copy of the full state of the object that it will keep, unlike Undo.RecordObject(Object objectToUndo, string name) that will only keep a copy of the state until the end of the frame to compute a diff.

By the way, I just got the following error that drove me to find more on this method:

Generating diff of this object for undo because the type tree changed.
This happens if you have used Undo.RecordObject when changing the script property.
Please use Undo.RegisterCompleteObjectUndo

So RegisterCompleteObjectUndo seems important in complex situations were a diff is not possible.

Undo.RegisterFullObjectHierarchyUndo will indeed copy the state of a game object and all its children and components, but it will react differently with different kind of objects. The documentation gives more details on this.

I just use SerializedProperty in my Editor code for full support for undo/redo… The documentation for Editor shows its usage.