- Home /
Detect when GameObject has been deleted / removed from scene
Is there a way to determine when an object has been removed from the scene in the editor (eg the user has selected the object and pressed 'delete').
I would have expected OnDisable() to be called, but it doesn't seem to be.
Answer by slkjdfv · Sep 02, 2013 at 12:31 PM
What I did to detect when an object is destroyed in edit mode is add a custom editor to it. So you create a blank script and attach a custom editor to it. In the custom editor use the OnDestroy method. Now this will get called even if you just deselect the object so in that method you need to check if the target script is null. If it's null you have deleted the object. So when you run the game since this is just for the unity editor you can tell it to remove this component at run time if you want. Here are the scripts :
using UnityEngine;
using System.Collections;
public class ObjectChecker : MonoBehavior
{
//Nothing needed here
}
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(ObjectChecker))]
public class ObjectChecker : Editor
{
public void OnDestroy()
{
if ( Application.isEditor )
{
if(((ObjectChecker)target) == null)
//Do your code here
}
}
}
Now this is a custom class for checking if the object is destroyed. You can put this OnDestroy code in any of your custom editor scripts if you want it to do something before the object is destroyed. This works for me with no issues. I use it in allot of my custom editors.
Thanks, This works well, but how to access the target's monobehaviour before it becomes null?
Target is only null if you delete the GameObject or Remove the script component from the GameObject, other wise it's never null. For example, in the OnDestroy $$anonymous$$ethod target is already assigned cause it's a custom editor. you need to convert it to your class before it becomes usefull, but you can already access it. When you have a class inherit from Editor it acquires the variable "target". If you don't know how to make a custom editor check the UnityDocs for help on how to get started.
public void OnDestroy()
{
if ( Application.isEditor )
{
if(((ObjectChecker)target) == null)
//Do your code here
}
}
Well. I mean, when I delete a gameObject, I want to access some of its member variables and functions before it's deleted. But in this code snippet. target is null. Any ideas how to do that?
To get deleted object in OnDestroy you can save it to static variable in OnDisable like this:
[CustomEditor(typeof(HorizontalPortal))]
public class HorizontalPortalEditor : Editor
{
static HorizontalPortal lastPortal;
protected void OnEnable()
{
portal = (HorizontalPortal)target;
}
protected void OnDisable()
{
lastPortal = portal;
}
protected void OnDestroy()
{
if (target == null)
{
lastPortal.DoSomething();
lastPortal = null;
}
}
}
@Lev Lukomskyi I tested your method but lastProtal
cant cache protal
since target
and portal
are both null
already when executing OnDisable()
. What version were your method working? I'm using Unity 5.1 now and I think maybe the implementation has been changed...
Answer by paraself · Sep 02, 2013 at 05:05 AM
Using ExecuteInEditMode and OnDestroy wont completely solve the issue. Because OnDestroy is also called when you hit play button in editor. For explicit detection of users deleting gameobject, my solution is:
For example, we have a xxx.cs monobehaviour attach to the gameobject that we wanna have deletion detection. Implement a corresponding editor script of xxx.cs like xxx_editor.cs (if you dont know how to do this, look at this tutorial link text)
in this xxx_editor.cs implement :
void OnSceneGUI(){
if (Event.current.commandName=="Delete") Debug.Log(target.name +" is deleted");
}
now you can easily detect gameobject deletion right in side the editor script, however it might be triggered multiple times because OnSceneGUI is called multiple times a frame. but I am sure that's easy to solve.
PS: it only detect deletion in Scene view, if deletion happens in hierarchy, then it doesnt work. prbly need to use EditorApplication.hierarchyWindowChanged
This is so painful if the user wants to delete from the inspector... I wish the custom Editor captured all events happening to objects it managed.
Although this method does most of the work, there is a little problem lingering. When application is done playing, upon returning to unity the OnDestroy method is called when it does not actually indicate a removal from the hierarchy. I managed to overcome it using a little boolean cache. Check the answers for my answer and you'll see the code.
Answer by Statement · Dec 16, 2010 at 03:07 PM
Your script must have ExecuteInEditMode attribute for that event to fire.
This will allow OnEnable, OnDisable etc be called when objects are created, when the game is run, stopped and object being deleted.
- Note that adding this attribute might cause other problems since other methods might be called as well, depending on your script. Read the docs.
Thanks - it isn't clear to me how to tell that the object has been deleted in OnDisable(). This: http://answers.unity3d.com/questions/9123/ondestroy-notification suggests that there's not enough information available in OnDisable() to tell the different between disabling and deleting.
Answer by luislodosm · Apr 24, 2017 at 07:52 AM
This works for detecting deleted objects in scene and hierarchy.
[ExecuteInEditMode]
public class MyClass : MonoBehaviour
{
void OnDestroy ()
{
if (Event.current != null && Event.current.commandName == "Delete")
DoStuffBeforeDie ();
}
}
This got me really close to a solution, on Unity 2019.4, commandName isn't "Delete" when the object is being deleted from the hierarchy but "SoftDelete" so I used this code to make it work:
private void OnDestroy()
{
if (Event.current != null && Event.current.commandName.Contains("Delete"))
{
DoSomethingWhen$$anonymous$$anuallyDestroyed();
}
}
Also unfortunately, not event is triggered when deleted via the context menu in the hierarchy...
Answer by rklaus · Dec 12, 2016 at 10:23 PM
Extending on @slkjdfv's answer, there is one slight problem with the solution. When application play is terminated, the OnDestroy
method gets called too. To overcome this problem, I implemented and tested this solution:
[CustomEditor(typeof(MyObject))]
public class MyObjectEditor : Editor
{
private bool mRunningInEditor;
private void OnEnable()
{
mRunningInEditor = Application.isEditor && !Application.isPlaying;
}
public override void OnInspectorGUI()
{
// do the magic here
}
public void OnDestroy()
{
if (mRunningInEditor && target == null)
// Code here for the actual object removal
}
}
wow! THIS should be the accepted answer! It works! Thank you
Edit/Update: Actually no, sometimes it also runs when you enter Play mode. For the final solution check my answer
Your answer
Follow this Question
Related Questions
OnDestroy() callback in Editor upon deleting selected GameObject - del key 5 Answers
Need help reassigning variables after the deletion of an object has been undone. 0 Answers
OnDestroy called when object lost focus in editor 2 Answers
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers