- Home /
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?
Answer by huulong · Oct 21, 2016 at 10:52 PM
The Unity documentation has been updated since:
https://docs.unity3d.com/ScriptReference/Undo.RegisterCompleteObjectUndo.html https://docs.unity3d.com/ScriptReference/Undo.RegisterFullObjectHierarchyUndo.html
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.
Answer by Jamora · Jan 13, 2014 at 02:59 PM
I just use SerializedProperty in my Editor code for full support for undo/redo... The documentation for Editor shows its usage.
Fair enough. But I have several hundred components, of varying degrees of complexity, and going back to refit them all as serialised properties isn't likely to happen. Plus I'd still like to know more about these undocumented functions for the cases where SerializedProperty et al. isn't appropriate.
Never having used the methods in question, the best advice I can give you is to get a (free) .net decompiler and see for yourself what Unity does inside those functions. If they're all calls to the native side, you're out of luck.
That actually doesn't help here as they just call their C++ code there, so you see nothing.