Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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 eshan-mathur · May 15, 2016 at 03:56 AM · c#monobehavioureventsmemory-leaklisteners

Does calling Destroy() on a GameObject/MonoBehavior drop references to any event listeners?

I know that source objects (defined as the object who owns the event) will keep a reference to anyone who is listening to it's events, so it's important to make sure the listeners unsubscribe lest you cause a memory leak.

I'm now wondering the reverse - if I call Destroy() on GameObject SourceObject with MonoBehavior SourceScript on it, will that drop references to anyone who is listening to SourceScript's events?

Or, do I have to make sure that all the listeners unsubscribe themselves from SourceScript's events before it gets destroyed?

Comment
Add comment
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

1 Reply

· Add your reply
  • Sort: 
avatar image
4
Best Answer

Answer by Bunny83 · May 15, 2016 at 11:18 AM

Yes they are dropped as long as all references to the source script instance are gone. Keep always in mind that inside the managed world it's not possible to destroy any object. When you call Destroy on a gameobject / Monobehaviour you only destroy the native C++ counterpart. The managed part of the object will remain as long as there is a reference to it somewhere inside the managed world.

If you have a reference to your sourceScript in a thrid script like that:

 public MySourceScript script;

and you destroy that instance by calling Destroy on the script or the containing gameobject the source script native part will be destroyed and the managed part will be marked as destroyed but still remains in memory until all references to it are gone so it can be garbage collected.

The script variable above will appear to be null after you call Destroy, but it actually isn't. Unity fakes that the reference is null when the object has been destroyed.

So the actual managed part of the instance will still remain and if it has an event with other subbed objects they will remain as well until the reference to the dead source script instance is gone, In that case the GC will clean up all left over objects.

The check

 if (script == null)
     script = null;

seems silly but actually has a use in Unity. It removes the fake null reference and allows the GC to collect the managed object.

Of course when you set a new instance to the variable the old reference will be gone as well.

Comment
Add comment · Show 7 · 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 eshan-mathur · May 15, 2016 at 05:26 PM 0
Share

Ah crazy! That's a lot of memory leaks waiting to happen. So Destroy() should never be used without an accompanying "= null"?

avatar image Bunny83 eshan-mathur · May 16, 2016 at 12:50 AM 0
Share

Well, only if the variable does persist in some way. In most cases where you destroy objects you don't keep references to those classes. So i wouldn't bother too much about that issue. Those "leaks" are not real leaks. A memory leak is something that keeps the memory loaded but isn't accessible any more. That's not possible in the managed world. So sooner or later the reference will be either overwritten or it goes out of extent. In both cases the object that was referenced is garbage collected.

avatar image Nick62 · Jul 07, 2019 at 06:52 PM 0
Share

@Bunny83, can you, please, explain.

If I have two $$anonymous$$onoBehaviours on the same gameObject and assign references in the inspector:

 public class A : $$anonymous$$onoBehaviour {
 
     public B b;
 
     void Start () {
         DestroyItself();    
     }
   
     private void DestroyItself(){
         b.a = null; // shoud I do this ?
         b = null; // shoud I do this ?
         
         Destroy(this);
     }
 }

//---

 public class B : $$anonymous$$onoBehaviour
 {
     public A a;
 }

Should I write these lines to delete $$anonymous$$onoBehaviour properly: b.a = null; and b = null; that GarbageCollector could collect this instance of class A????

Or may be only one of them?

//==================================

//==================================

And other situation: If I have else one $$anonymous$$onoBehaviours on the same gameObject

    public class C : $$anonymous$$onoBehaviour
    {
            public A a;
             public B b;
           
    void Start(){
         Destroy(a);
         Destroy(b);
         Destroy(this);
    }
 }

Shoud I assign a and b to null in this case?

avatar image Bunny83 Nick62 · Jul 07, 2019 at 08:11 PM 1
Share

Well, your cases are very abstract. In your first case if "B" should not be destroyed, then yes, setting b.a = null; would help the GC to actually clean up the destroyed instance of A. In your second case, I'm not sure when this is actually the case. If you actually destroy all those scripts, why is the gameobject still there?


The general rule is simple: As long as there is any static field or any active script with a field the references other monobehaviour scripts, the static variable or the instance fields of the remaining class instance will keep a destroyed object still alive. The reference chain can go as deep as you want. So as long as a class isn't garbage collected (because there's somewhere still a reference to it) it will keep all the instances alive that it references in its own fields. The only exception are circular references between multiple classes which are all no longer referenced by any active object (or a static variable).


Imagine you have a class A that is still alive on a gameobject. There might be other objects (B,C,D,E,F) which all have been destroyed with Destroy. There might be a reference chain like this:

  A
  |
 \|/
  B-->C-->D-->E
 /|\          |
  \___________/

Since A is still alive all those objects will stay alive. However when we clear the reference in class A it becomes this:

  A
 
 
  B-->C-->D-->E
 /|\          |
  \___________/

B,C,D and F are all destroyed objects and no longer referenced from an active object. So they can be garbage collected since there are only references between objects that are all up for garbage collection.

avatar image Nick62 Bunny83 · Jul 07, 2019 at 08:26 PM 0
Share

Thank you, @Bunny83 !

But what do you mean " would help the GC to actually clean up the destroyed instance of A." ?

Would component A collected by GC without this line b.a = null; ?

Show more comments

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

144 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 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 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 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 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 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 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 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 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

Multiple Cars not working 1 Answer

How to subscribe method to OnDisable in a gameObject. 1 Answer

Unity Events, Listeners, Delegates, etc. 1 Answer

Distribute terrain in zones 3 Answers

Call AddListener on sibling components from MonoBehaviour.Reset 0 Answers


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