Editor.DestroyImmediate crashes Unity. Am I using it wrong?

I have a number of empty group nodes in Maya that contain user-data. I'm using an Editor Script to call OnPostprocessGameObjectWithUserProperties to use this data. That all works perfectly fine and my data is used well. Now I want to get rid of the empty game objects so that they're not cluttering up my model's hierarchy, but it always seems to crash Unity. I have:

using UnityEngine;
using UnityEditor;
using System.Collections;

public class ModelImport : AssetPostprocessor 
{

    void OnPostprocessGameObjectWithUserProperties( GameObject go, string[] names, object[] values) 
    {
        // Do some stuff
        Editor.DestroyImmediate(go, true); // This line causes Unity to crash to desktop
    }
}

Anyone have an idea what I'm doing wrong, or rather, what I should be doing instead?

Just wondering: what's the 'true' for? I've just used a DestroyImmediate(theGameObject); and everything works fine everytime. Though Editor script errors do tend to screw/crash Unity.

Oh, that I forgot to take out, but it doesn't change anything about it not working. Putting true there allows DestroyImmediate to destroy assets, rather than just GameObjects. It defaults to false, and I had put true in an attempt to get things not to crash, but there's no difference.

3 Answers

3

OnPostprocessGameObjectWithUserProperties iterates through all containing objects when importing an asset. I guess when you destroy it here Unity's current iteration will continue on the destroyed object. I don't even understand why you want to destroy the whole asset in the postprocessor...

Well, if you really want to destroy it (maybe due to some user data set) you could try to destroy it in AssetPostprocessor.OnPostprocessModel. You just have to keep track of your condition. If that doesn't work either you could create a temp GO with a special script (ExecuteInEditMode) and let it delete the asset (and itself). Well, it should even be possible to add a selfdestruct script to the asset but i think OnPostprocessModel should work.


edit

You can try AssetDatabase.DeleteAsset. It should also be capable of deleting just a subobject. If it doesn’t work just use a List<> to store the Objects you want to delete and do it later, maybe in AssetPostprocessor.OnPostprocessAllAssets. Just delete all objects in your list.

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

public class ModelImport : AssetPostprocessor 
{
    private List<GameObject> m_ObjectsToDelete = new List<GameObject>();

    void OnPostprocessGameObjectWithUserProperties( GameObject go, string[] names, object[] values) 
    {
        // Do some stuff
        m_ObjectsToDelete.Add(go);
    }
    void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath)
    {
        foreach(GameObject go in m_ObjectsToDelete)
            DestroyImmediate(go,true);
        m_ObjectsToDelete.Clear();
    }
}

I haven't tested it yet, but it should work.

I don't want to destroy the whole asset, I only want to remove that one GameObject node that has the data on it. For example, my model consists of three meshes and two empty group nodes with user data on it. I want to remove those two empty group nodes so that when I import the model and expand the hierarchy, I only see the three meshes. AssetPostprocessor.OnPostprocessModel won't work because that works on the entire asset, not on the individual game objects that contain the data.

edit* ;) Did you even check for any special userdata or do you just want to remove everything that contains userdata?

Well, i just forgot that in C# you need to add using System.Collections.Generic;

So the error is gone, but its still not doing anything for OnPostprocessAllAssets. It's like it never actually gets called. I've found a work-around by naming the created nodes specifically, and then in a separate OnPostprocessModel routine that is called later, I look for game objects named as such and remove them. I don't like doing it that way because it feels wrong, but it's functional for now. Interestingly enough, Editor.DestroyImmediate works in that scenario, but does not in the original scenario.

I guess OnPostprocessGameObjectWithUserProperties is the only one of these events that cause problems. Maybe because of the userdata it's providing. I haven't used this function so i can't tell. Have you even tried the "normal" Destroy? Because the docs say it can also destroy assets. Destroy is the saver method since it's delayed and Unity destroy the object when it's save to do so. Or is there a reason you use DestroyImmediate ?

I know this question is old, but I just wanted to add a comment, since it is still useful!
I had the same problem, and when I tried to put the game objects to be deleted into a list and delete them in OnPostprocessAllAssets, nothing happened.

By the way, the method has to be static, otherwise it won’t be called!

However, deleting the object in there didn’t work.

Therefore I also rename my object to “DeleteMe” and check for the name in OnPostprocessModel.

Destroy destroys asynchronously.

DestroyImmediate works in test environment, but crashes my target App.

Editor.DestroyImmediate works in test environment, but crashes my target App.

OnPostprocessAllAssets is just bad implementation to do something that should be done with synchronous Destroy.