- Home /
Undo.RecordObject isn't working.
I am using Undo.RegisterUndo method to register undoable actions but in Unity 5.x it says it's obsolete and asks me to use Undo.RecordObject instead. But the problem is RecordObject method does not work while RegisterUndo does. What am I missing here?
What I'm doing : I'm customizing Transform's inspector window and I pass a cast Transform object to Undo.RecordObject method.
Undo.RecordObject(target, "Edit Transform"); works fine here
Weird, although this isn't working for me :
private void ResetPosition(Object[] objs)
{
for(int i = 0; i < objs.Length; i++)
{
Transform tr = (Transform)objs[i];
Undo.RecordObject(tr, "Transform Change");
tr.position = Vector3.zero;
}
}
while this does :
private void ResetPosition(Object[] objs)
{
for(int i = 0; i < objs.Length; i++)
{
Transform tr = (Transform)objs[i];
Undo.RegisterUndo(tr, "Transform Change");
tr.position = Vector3.zero;
}
}
Lol am I missing something or what?
Both works here XD (Sorry I changed it to GameObject it was easier for me) Try this :
private void ResetPosition(GameObject[] objs)
{
foreach (GameObject tr in objs) {
Undo.RecordObject (tr.transform, "$$anonymous$$ove" + tr.name);
tr.transform.position = Vector3.zero;
}
}
Unity 5.2
$$anonymous$$y code does the same thing. RegisterUndo works but RecordObject does not?? but unity is complaining that RegisterUndo is obsolete?
p.s. im also using objects not an object. I'm moving a bunch of things and want them all to move back on undo. Undo.RegisterUndo(walls, "Aligning Walls");
where walls is a list of objects
oh and use the foreach(GameObject obj in objects)
you save a line of code by not using for(int i; i <objs.length
etc... ahh what a pain to read.
Answer by IgorAherne · Jul 19, 2017 at 10:12 PM
I found this post by complete accident:
quoting it in case it's deleted:
.
Undo.RegisterCompleteObjectUndo(Object objectToUndo, string name)
will record a copy of the full state of the object that it will keep, unlikeUndo.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.
Couple of words from myself:
Undo.RegisterCompleteObjectUndo seems to work with Event and editor-GUI as well every time. And RecordObject seemed only to work sometimes (only worked occasionally)
Additionally, if you are working with Event in editor script, and actually have code that Use()s the GUI event, chances are the event might not get through to unity's undo system. You might need to call Undo.FlushUndoRecordObjects(); after RegisterCompleteObjectUndo()
.
Don't forget to use EditorUtility.SetDirty() on the object, AFTER you've recoreded into Undo
Here is an example, allowing me to offset 2D viewport up/down left/right:
void DragViewingArea() {
int id = GUIUtility.GetControlID(6, FocusType.Passive);
//prepare for drag:
if (_currentEvent.type == EventType.MouseDown && _currentEvent.button == 2) {
Undo.RegisterCompleteObjectUndo(_fsm, "begin drag FSM viewport on " + _fsm.gameObject.name);
Undo.FlushUndoRecordObjects();
GUIUtility.hotControl = id;
_currentEvent.Use();
return;
}
//drag:
if(_currentEvent.type == EventType.MouseDrag && GUIUtility.hotControl == id) {
_fsm._fsmEditorWindow_TableOffset += _currentEvent.delta;
_currentEvent.Use();
EditorUtility.SetDirty(_fsm); //set dirty as soon as we actually drag
return;
}
//finished dragging
if (_currentEvent.type == EventType.mouseUp && _currentEvent.button == 2 && GUIUtility.hotControl == id) {
GUIUtility.hotControl = 0;
_currentEvent.Use();
return;
}
}
Answer by D-Lask · Oct 19, 2015 at 07:06 PM
You have to make sure to call Undo.FlushUndoRecordObjects()
to make sure changes made after calling RecordObject
are pushed onto the Undo stack.
Answer by Chuckalicious · Apr 13, 2016 at 04:39 PM
I have the same issue and it seems to happen with changes on my 1024 X 1024 terrain vs. 50 X 50. Also, Undo.FlushUndoRecordObjects() is automatically done; so, not sure why I would need to explicitly call that. I tried but it didn't help anyway. The RegisterUndo does work though. I suspect a bug in RecordObject and will continue to use the deprecated method until I hear otherwise.
Yeah. I've not changed my code add it is working. Until it is depreciated completely I will keep the same. Not that I've needed to undo anything since all my editor code does is align my tiles.
Answer by Andy-Korth · Oct 11, 2016 at 07:58 PM
In your example, you have:
private void ResetPosition(Object[] objs)
{
for(int i = 0; i < objs.Length; i++)
{
Transform tr = (Transform)objs[i];
Undo.RecordObject(tr, "Transform Change");
tr.position = Vector3.zero;
}
}
Don't record the change on the Transform, instead record it on the GameObject:
private void ResetPosition(Object[] objs)
{
for(int i = 0; i < objs.Length; i++)
{
Transform tr = (Transform)objs[i];
Undo.RecordObject(tr.gameObject, "Transform Change");
tr.position = Vector3.zero;
}
}
This is not explained in the docs, but the examples hint at it. Another source: http://answers.unity3d.com/answers/1007419/view.html
That won't change anything. The parameter type of RecordObject is "UnityEngine.Object". So it doesn't matter if you first down-cast it to Transform as it is implicitly up-casted when you pass the transform to RecordObject. This can't have any impact on the outcome. $$anonymous$$eep in $$anonymous$$d an up or downcasted reference is still the exact same reference. Just the variable has a different type.
Casting of objects does not change the object's type. That's not possible at all. An object will always have its actual concrete type no matter what. An up-cast is always possible while a down-cast requires a type check at runtime since not every "object" can be casted to "Transform", but every Transform can be casted to "object".
The answer you linked doesn't say to pass an "object" or "Object" reference but ins$$anonymous$$d of a reference to the Transform component that you changed you should pass the containing GameObject to which this transform component belongs to.
Oops. You're correct. I seem to have confused myself with another example I was looking at elsewhere. I thought he was casting it to a GameObject and calling gameObject.transform. I will update my answer accordingly.
This was my answer. I was changing a property inside the object. Using target.object ins$$anonymous$$d worked.
Answer by alfish · Oct 09, 2017 at 09:07 PM
I had a somewhat related problem, where the undo wasn't working in a specific object. It was an editor-only object (had hideflags) but I needed it to update on an undo operation. In my case, it turned out that I forgot to add SerializeField on the fields (or make them public), so the undo wasn't registering the fields.
Thank you! This is exactly the problem that most people have.