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
1
Question by ThePunisher · Nov 26, 2013 at 11:14 PM · objectdestroyreferencememoryleak

Is a unity object really destroyed if its destructor was never called?

Ok, this might be a little complicated to explain so bear with me. I have made a very simple test environment with two test scripts that allows me to determine if a particular activity will cause a unity object to leak even though Destroy has been called on it.

I have a script called MyScript which I attach to an empty GameObject. Then I have a different script called TestScript placed on a different GameObject (Main Camera in my case) which grabs a reference to the first GameObject(i.e MyScript). If I hit the Destroy button then you will notice that an "OnDestroy" log statement will appear in the console window, followed by a "Destructor" log statement shortly after. To me this verifies that the object was completely destroyed and garbage collected. Please let me know if that is not correct.

Now, if I un-comment the following line of code //dr = m_go.GetComponent(); inside TestScript and explicitly grab a reference to the MyScript component on the GameObject, then I hit the Destroy button something different happens. The "OnDestroy" still gets called by Unity but we get no "Destructor" log statement. Does this mean that the object MyScript was not garbage collected? It would make sense to me that was the case since I'm holding a reference to it, but I'm not entirely sure since Unity seems to null out my reference to the component. You can verify this by hitting the Check button which will output null.

The reason I ask is because our games are riddled with references to the components which are retrieved through public inspector properties of a particular type, instantiating of a prefab through a script type, or just simply retrieving the component from the GameObject, and when we want to destroy the object we call Destroy(MyScript.gameObject) which produces what seems to be a leak if we still had a reference to the script.

Some of you may already be familiar with this, however I was not, so I would appreciate any input/feedback/clarification you guys have. Here are the scripts:

 using UnityEngine;
 using System.Collections;
 
 public class MyScript : MonoBehaviour
 {
     public TestScript hold;
 
     private void Start()
     {
         //hold.Del = Handler; //Does not call destructor.
     }
 
     private void Handler()
     {
         
     }
 
     private void OnDestroy()
     {
         Debug.Log("bye :(");
     }
 
     ~MyScript()
     {
         Debug.Log("Destructor");
     }
 }



 using UnityEngine;
 using System.Collections;
 
 public class TestScript : MonoBehaviour
 {
     public TestDelegate Del;
 
     private GameObject m_go;
 
     private MyScript dr;
 
     private void Start()
     {
         m_go = GameObject.Find("GameObject");
         //dr = m_go.GetComponent<MyScript>(); // Does not call destructor
     }
 
     private void OnGUI()
     {
         if (GUI.Button(new Rect(0, 0, 100, 50), "Destroy"))
         {
             Destroy(m_go);
         }
 
         if (GUI.Button(new Rect(0, 50, 100, 50), "Check"))
         {
             Debug.Log(dr);
         }
     }
 }
 
 public delegate void TestDelegate();
 
Comment
Add comment · Show 2
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 ThePunisher · Nov 26, 2013 at 11:17 PM 0
Share

I also want to point out that if I change the code for test script to the following then it will produce the same effect:

 using UnityEngine;
 using System.Collections;
 
 public class TestScript : $$anonymous$$onoBehaviour
 {
     public TestDelegate Del;
 
     public $$anonymous$$yScript component;
 
     private $$anonymous$$yScript dr;
 
     private void Start()
     {
         //dr = m_go.GetComponent<$$anonymous$$yScript>(); // Does not call destructor
     }
 
     private void OnGUI()
     {
         if (GUI.Button(new Rect(0, 0, 100, 50), "Destroy"))
         {
             Destroy(component.gameObject);
         }
 
         if (GUI.Button(new Rect(0, 50, 100, 50), "Check"))
         {
             Debug.Log(dr);
         }
     }
 }
 
 public delegate void TestDelegate();
 
avatar image ThePunisher · Nov 26, 2013 at 11:19 PM 0
Share

Updating the Destroy code to this will get the destructor to be called again:

 if (GUI.Button(new Rect(0, 0, 100, 50), "Destroy"))
         {
             var go = component.gameObject;
             component = null;
             Destroy(go);
         }

1 Reply

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

Answer by aldonaletto · Nov 27, 2013 at 02:45 AM

From everything I've been reading about .Net/Mono memory management, it seems that a memory block is automatically disposed of by the garbage collector when there are no more references to it - thus, if you get a reference to MyScript, the garbage collector won't free it. If you want to know more details about .Net memory management, take a look at this article; there's also a relationship between a destructor and the Finalize callback function that's called by the garbage collector when disposing of an object (see this topic). To further complicate matters, Unity does some extra magic between Destroy and the actual object disposal, thus other surprises may arise from your tests.

Comment
Add comment · Show 3 · 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 ThePunisher · Nov 27, 2013 at 06:42 PM 0
Share

Thanks for the response. You weren't kidding about surprises. So you know how I'm logging the component under the Check button? Apparently, Unity is explicitly returning "null" to me because it thinks it has successfully destroyed the component, HOWEVER, if I add dr.ToString() right after Debug.Log(dr); it throws no exception (since it's not actually null). I'll be running other experiments and checking out what you linked.

avatar image aldonaletto · Nov 27, 2013 at 11:40 PM 1
Share

Take a look at Lucas $$anonymous$$eijer's post in the forum about how references become null when an object is destroyed - maybe this helps a little.

avatar image ThePunisher · Dec 02, 2013 at 06:31 PM 0
Share

Ah, what he said makes a lot of sense actually. Thanks for the responses, aldonaletto. Looks like I'll be having to set component references to null right after calling destroy then so these wrappers go away, lol.

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

18 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

Related Questions

Replace GameObject with another GameObject and preserve references without using Destroy() 0 Answers

,MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object. 0 Answers

destroy object collision problem 1 Answer

Getting all Object to go next scene. 1 Answer

Why the gameObject doesn't destroys? 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