- Home /
Destroy Child Object(s) OnValidate?
Is there any way to destroy child objects during OnValidate and/or in edit mode?
using UnityEngine;
public class DestroyChildrenTest : MonoBehaviour
{
private void OnValidate()
{
foreach (Transform child in transform)
{
DestroyImmediate(child);
}
}
}
The code above doesn't work and throws the following error message:
Destroying components immediately is not permitted during physics trigger/contact, animation event callbacks or OnValidate. You must use Destroy instead.
But using Destroy() instead also doesn't work and throws this error message:
Destroy may not be called from edit mode! Use DestroyImmediate instead.
I've tried using co-routines and WaitForEndOfFrame() or WaitForFixedUpdate(), but that didn't seem to do anything.
Answer by MikeNewall · Feb 26, 2017 at 01:20 AM
In the editor the method you suggested should work.
Use a coroutine to wait until the end of the frame and then destroy the gameobject.
public bool toggleValidation;
void OnValidate () {
foreach (Transform child in transform)
{
StartCoroutine(Destroy(child.gameObject));
}
}
IEnumerator Destroy(GameObject go)
{
yield return new WaitForEndOfFrame();
DestroyImmediate(go);
}
Aha. So you need a co-routine for each object you want to destroy. I just tried running a for loop for all the objects after WaitForEndOfFrame but that doesn't work apparently. Not exactly sure why this is the case, but thanks for the answer!
Thanks for this precision, indeed I tried first to use only one coroutine for all objects and Unity seemed to Destroy only half of the objects, ins$$anonymous$$d of all of them (why ? I don't know, another mystery of Unity way of life), at least one coroutine per object works well.
Actually in Editor$$anonymous$$ode (not Playing) the StartCoroutine
does nothing since in edit mode the IEnumerator.$$anonymous$$oveNext()
is never called ...
For those reading this later, replace:
yield return new WaitForEndOfFrame();
with:
yield return null;
Answer by janus1001 · Feb 27, 2017 at 11:52 AM
First of: typo in class name.
And for the answer:
If OnValidate() doesn't work, why not get rid of it?
The solution consists of adding a custom button in the inspector and discarding the OnValidate() function. It is clearer and better, yet can be confusing if you never tried creating your own inspector.
Basically, what you will do is add a new script, which will hold the functions of the custom inspector, in this case a button and paste in the two scripts I provided in the end. I don't know whenever you know the topic, so I won't explain every aspect of the code, it is pretty basic. Fix the typo.
Script for replacement with current one:
using UnityEngine;
public class DestoryChildrenTest : MonoBehaviour
{
public void DestroyChildren()
{
foreach (Transform child in transform)
{
DestroyImmediate(child.gameObject);
}
}
}
New script (name doesn't matter)
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(DestoryChildrenTest))]
public class ObjectBuilderEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
DestoryChildrenTest myScript = (DestoryChildrenTest)target;
if (GUILayout.Button("DestroyChildren"))
{
myScript.DestroyChildren();
}
}
}
Yeah, I keep misspelling "destroy" for some reason :$
If OnValidate() doesn't work, why not get rid of it?
Well, OnValidate() is most convenient here because I want to destroy and rebuild child objects whenever I change a value in the inspector. I did actually think about creating a button, but I only want to use that if nothing else works. Fortunately, $$anonymous$$ike Newall has shown an easy solution to my problem, but thanks for your example anyway!
I can also see now that the toggleValidation variable included in the sample code was somewhat misleading. This was only added for testing the OnValidate() callback, but I guess including it was unnecessary and confusing. $$anonymous$$y bad.
This is the only solution i've read that worked. I tried all the others. Possibly to do with being on 2017 version.
Answer by jdean300 · Feb 26, 2017 at 01:04 AM
You could create a class in your editor folder marked InitializeOnLoad
with a set of GameObjects to delete:
[InitializeOnLoad]
public class Example {
public static HashSet<GameObject> DestroyOnUpdate = new HashSet<GameObject>();
// ... the following code...
}
In it's static constructor, register a callback for EditorApplication.update
:
static HierarchyDecorator()
{
EditorApplication.update += Update;
}
In the Update method, delete any GameObjects if you are in edit mode:
public static void Update()
{
if (EditorApplication.isPlaying)
return;
foreach (var go in DestroyOnUpdate) {
Destroy(go);
}
DestroyOnUpdate.Clear();
}
In a components validate method, add the gameObject you want to destroy to the list:
private void OnValidate(){
Example.DestroyOnUpdate.Add(gameObject);
}
This is a bit heavy handed, but should work.
This is probably a bit too complex and doesn't exactly fit my needs, but others might find the suggestion useful so thanks for posting it anyway!
Answer by blastbeatsandcode · Oct 05, 2019 at 09:04 PM
This question is a couple of years old, but I just encountered this same problem. The answer by @MikeNewall is partially the solution, but you can't run coroutines in the editor mode although it may be coming to Unity eventually according to this.
I found a workaround using this little library: Unity Editor Coroutines.
This makes deleting the GameObjects
really simple.
public bool toggleValidation;
void OnValidate () {
foreach (Transform child in transform)
{
// The really important part, using the library
EditorCoroutines.EditorCoroutines.StartCoroutine(Destroy(child.gameObject), this);
}
}
IEnumerator Destroy(GameObject go)
{
yield return new WaitForEndOfFrame();
DestroyImmediate(go);
}
Answer by zerodragonheart · Jan 30, 2020 at 05:22 PM
i'm having the same issue with this line var go = Instantiate(FloatingTextprefab,this.transform.position,this.transform.rotation); go.GetComponent().text = finaldamage.ToString();
I don't know why
Your answer
Follow this Question
Related Questions
Hierarchy Foldout Variables Wanted 3 Answers
Fold/unfold gameobject from code 4 Answers
Open Reference Button Opens Notepad++ Instead of Taking me to the Documentation 1 Answer
How to specify the rotation angle in degrees, in the inspector? 2 Answers
Can a GameObject's full inspector be drawn in a custom Editor Window ? 1 Answer