Search Unity

  1. Full schedule for #UniteBerlin is now available! Featuring talks on our roadmap, hands-on labs and much more! Check it out!
    Dismiss Notice
  2. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  3. Scriptable Render Pipeline improvements, Texture Mipmap Streaming, and more! Check out what we have in store for you in the 2018.2 Beta.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. 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:
    33
    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.