Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Recording destroyed object inside OnDestroy() method

Discussion in 'Extensions & OnGUI' started by Aridez, Apr 7, 2018.

  1. Aridez

    Aridez

    Joined:
    Feb 12, 2014
    Posts:
    7
    I have a custom editor made to create graphs. Usually the nodes can be deleted using the editor tools, so when I destroy the node object I can just call:

    Undo.DestroyObjectImmediate(node);


    The problem comes when the user doesn't use the editor, I want to fully implement this case since it's something that can happen and I don't want users to break the whole graph when deleting nodes directly, so I implemented the following method inside the "Node" class:

    Code (CSharp):
    1. [ExecuteInEditMode]
    2.         private void OnDestroy() {
    3.             for (int i = 0; i < outs.Count; ++i) unlinkFrom(outs[i]);
    4.             for (int i = 0; i < ins.Count; ++i) ins[i].unlinkFrom(this);
    5.             Undo.RecordObject(getParent(), "destroyed");
    6.             getParent().remove(this);
    7.         }
    This basically removes all the edges connecting to this node. But I wanted to implement an "Undo" function to this part too I tried the following things:

    • Record the object with the line "Undo.RecordObject(this)" at the beginning/end of the function, it still doesn't recover the references of adjacent nodes

    • Using the same line "Undo.DestroyObjectImmediate(this)" at the end of the function, it works! But an error pops out on the console saying that I can't call "DestroyImmediate" inside "OnDestroy".
    Is there any way to record a destroyed object inside the "OnDestroy" function? Or a way to avoid that error message from showing up in the console?

    Thanks!

    Just for reference, this is the version that actually works throwing the error message on the console

    Code (CSharp):
    1.     [ExecuteInEditMode]
    2.     private void OnDestroy() {
    3.         for (int i = 0; i < outs.Count; ++i) {
    4.             Undo.RecordObject(outs[i], "destroyed");
    5.             unlinkFrom(outs[i]);
    6.         }
    7.         for (int i = 0; i < ins.Count; ++i) {
    8.             Undo.RecordObject(ins[i], "destroyed");
    9.             ins[i].unlinkFrom(this);
    10.         }
    11.         Undo.RecordObject(getParent(), "destroyed");
    12.         getParent().remove(this);
    13.         Undo.DestroyObjectImmediate(this);
    14.      
    15.     }
     
  2. NoBrainer-David

    NoBrainer-David

    Joined:
    Jan 5, 2014
    Posts:
    34
    You have to start recording the object before you make changes to it, otherwise those changes can't be recovered. In your first code example, maybe just move the line where you start recording the object to the top?
    If ins[] and outs[] is not part of the current type, but of whatever getparent() returns, that might also be the problem why it is not recording that change.

    I would need to see more of your node class hierarchy to make any more suggestions.
     
  3. Aridez

    Aridez

    Joined:
    Feb 12, 2014
    Posts:
    7
    Hey thanks for the reply!

    In the end I got it working using the "Undo.RegisterCompleteObjectUndo()" function. It seems that when dealing with object destruction using that makes a difference.