Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Steven-Walker · Mar 20, 2013 at 03:23 AM · destroycomponentdestroyimmediate

How to destroy linked components when object is destroyed?

I have a component which manages other components on the same object in the editor. I've implemented OnDestroy so that the primary component removes all of the ones it manages. This works fine when I want to delete the main component. However, if I delete the game object, I get the error:

Destroying object multiple times. Don't use DestroyImmediate on the same object in OnDisable or OnDestroy.

I can't seem to find a way around this. I'm testing for null before destroying and setting the references to null afterward, but I think Unity is trying to delete each component again after I've already deleted it. Is there a better way to handle the destruction of managed components?

My work around for now is to use a separate hidden child object to store the components, providing more certainty in destruction order. But I don't like this because it alters the hierarchy. I'm trying to keep the managed components hidden and unobtrusive. I've tried working with ScriptableObject as an alternative, but ran into insurmountable issues with prefabs and object duplication.

Comment
Add comment · Show 8
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Steven-Walker · Mar 20, 2013 at 03:25 AM 0
Share

I should have mentioned too: If I don't delete the managed components, then they remain after deleting the primary. There are potentially a lot of components and they're hidden, so it's important that they get deleted with their owner.

avatar image Julien-Lynge · Mar 20, 2013 at 05:24 AM 0
Share

Can you save the gameObjects to an array, pop them in a coroutine, and delete them in the next frame? Not an elegant solution, but I've never seen what you describe, so I'm not sure how to help you.

avatar image Julien-Lynge · Mar 20, 2013 at 05:25 AM 0
Share

Also, could you consider using ScriptableObject rather than game objects if all you're doing is storing components?

avatar image Steven-Walker · Mar 20, 2013 at 06:07 AM 0
Share

Since this is all being done in editor mode (not playing), I can't make use of yield or coroutines. And yes, I have tried the ScriptableObject route but it poses difficult problems with duplicating and prefabs.

avatar image Julien-Lynge · Mar 20, 2013 at 06:17 AM 0
Share

Sorry, I somehow completely missed that this was happening in the editor. I'll have to give it some more thought.

Show more comments

1 Reply

· Add your reply
  • Sort: 
avatar image
3

Answer by beck · Feb 24, 2014 at 03:21 AM

I had this same issue and I was able to solve it by passing the destroy code in an anonymous function to EditorApplication.delayCall.

 [ExecuteInEditMode]
 public class MyComponent : MonoBehaviour
 {
 
   [Serializable]
   List<UnityEngine.Object> dependants = new List<UnityEngine.Object>();
 
   void OnDestroy ()
   {
 #if UNITY_EDITOR
     foreach(var d in dependants)
     {
       var o = d; // save in a different buffer to save state for anon func
       EditorApplication.delayCall += ()=>
       {
         if(o) GameObject.DestroyImmediate(o);
       };
     }
 #else
     foreach(var d in dependants)
     {
       if(d) GameObject.Destroy(d);
     }
 #endif
   }
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Sajidfarooq · Feb 24, 2014 at 08:30 PM 0
Share

Well done Beck! That snippet just saved me some frustration...

avatar image fawnha · Mar 02, 2014 at 09:45 PM 0
Share

This prevents the error when deleting the game object or opening a new scene however when I press play the child components I created in editor mode are destroyed and are not available in play mode. Any suggestions on how you got around this?

Solved: Actually I got around this by making the child component a ScriptableObject. It was originally just a Serializable class. The problem was that serializable classes are garbage collected on scene load because Unity can't detect that they are referenced in the scene. When I made the component a ScriptableObject it was not garbage collected because Unity detected that it had a reference in the controlling class which is in the scene.

Update: I now have a problem that I can't save the ScriptableObject in a prefab so I'm going to got back to C# serialisation and look for another solution.

avatar image beck · Mar 03, 2014 at 02:05 AM 0
Share

@fawnha You may be able to get around this by testing if(EditorApplication.isPlayingOrWillChangePlay$$anonymous$$ode)

avatar image mossyblog · Mar 18, 2016 at 07:07 AM 0
Share

The hell.. this one random thread saved me hours of google search deadzones... delayCall via onGUIChanged worked a treat.

avatar image CaseyHofland · Jul 24, 2020 at 12:08 AM 0
Share

Give this man a gold star. I would like to point out that #if UNITY_EDITOR applies, you still need to check for if(Application.isPlaying) and use Destroy if it is according to best practices.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

16 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Destroy(GetComponent(...)) not working 1 Answer

OnTriggerEnter - destroy (this.gameobject) if it collides with anything 2 Answers

Adding joints through script 2 Answers

Destroying a Transform Component 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges