• 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 Bugaga · Nov 07, 2012 at 09:06 AM · memorygcunloadunusedassetsfindobjectsoftypeall

Asset is not unloaded even if GameObject destroyed

I believe that this question was discussed many times, but still.

Consider an example: We have some kind of singleton class which exists all the time. It has public GameObject MyGameObject;

We load scene1. And set MyGameObject = GameObject.Find("Whatever"); Then we load scene2.

Now Debug.Log(MyGameObject == null) will say "true". I suppose somekind of wrapper still exists, which knows that this GameObject doesn't exists anymore. We can't even find it using FindObjectsOfTypeAll (and we can't find source asset). So Unity knows that object was destroyed, but it still keeps texture alive! (after calling UnloadUnusedAssets of course).

So until we excatly set MyGameObject = null; we can't get rid of texture it uses in our memory.

This is very simple example, in reality everything can be very unobvious. We can reference another class, which can refenrece gameobject which was destroyed and it's component can has delegate in which closure still exists local variable of another gameobject and etc.. I understand that this is our problem and we should keep eyes on our code, but I'm really interested in reasonable explanation why is it so?

Comment
Add comment · Show 9
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 Kryptos · Nov 07, 2012 at 09:56 AM 0
Share

Ins$$anonymous$$d of checking for null-value, you should explicitely release any references when loading a new level or destroying the object:

 void OnLevelWasLoaded()
 {
     this.$$anonymous$$yGameObject = null;
 }
avatar image Bugaga · Nov 07, 2012 at 01:47 PM 0
Share

Yes, I mentioned it. The whole question is not about how to handle with it, but why does it happen?

avatar image Kryptos · Nov 07, 2012 at 03:16 PM 0
Share

It happens because .Net use a reference implementation. If an object is referenced by at least one other object then it cannot release any memory (it is similar to reference counting in C++ but is done in a different manner).

To prevent this, you should make sure that you release all references to any resources when destroying an object. The best way is to use OnDestroy:

 public class Example : $$anonymous$$onoBehaviour
 {
     public Texture2D textureRef;
     public OtherScript scriptRef;
     public GameObject objectRef;

     void Start()
     {
         this.objectRef = GameObject.Find("objectname");
         this.textureRef = FindObjectsOfTypeAll(typeof(Texture2D))[0];
         this.scriptRef = objectRef.getComponent(typeof(OtherScript ));
     }

     void OnDestroy()
     {
         this.objectRef  = null;
         this.scriptRef = null;
         this.textureRef = null;
     }
 }

And in your singleton object:

 void OnLevelWasLoaded()
 {
     Resources.UnloadUnusedAssets();
     System.GC.Collect();
 }
avatar image valyard · Nov 07, 2012 at 03:23 PM 0
Share

But he said that Debug.Log($$anonymous$$yGameObject == null) outputs true. There must be some other object referencing $$anonymous$$yGameObject or textures it is using. Because if it is eligible for GC and it is the only object referencing a texture this texture should be GC'ed too.

avatar image Kryptos · Nov 07, 2012 at 03:26 PM 0
Share

$$anonymous$$aybe something is done wrongly is his project because I did use this method in an iOS project and the resources were unloaded as expected.

avatar image Bugaga · Nov 07, 2012 at 04:24 PM 0
Share

Omg. What I am trying to say is in my example is that: 1) texture deleting depends on gc/references in mono 2) $$anonymous$$yGameObject == null returns null even if we have some references - so it uses another safe aproach. Exception should happen but unity prevents it.

I know that I should null them. I know why it happens. But it so unobvious that almost every person here doesn't get fully the idea.

avatar image Kryptos · Nov 07, 2012 at 04:31 PM 0
Share

2) $$anonymous$$yGameObject == null returns null even if we have some references

Don't understand what you mean. $$anonymous$$yGameObject == null does not mean that there are no other references, just that this particular reference is null.

avatar image Bugaga · Nov 08, 2012 at 06:59 AM 0
Share

No..ok, example:

GameObject go = new GameObject("A"); Destroy(go); Debug.Log(go); // output "null" (1) go = null; Debug.Log(go); // output "null" (2)

Output is the same but meaning is different. In first one reference is still kept, some kind of wrapper still exists, and all the assets this gameobject uses won't be freed in memory. The second "null" is "real", everything is fine, memory will be freed. Actually there should be an exception on first output, but unity prevents it, helps us with this, but makes on the other hand everything more complicated.

avatar image Kryptos · Nov 08, 2012 at 08:47 AM 0
Share

Ok we already know that. But what do you want exactly?

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by valyard · Nov 07, 2012 at 01:54 PM

Unity doesn't unload textures from memory if objects using them are destroyed. It was mentioned in some of the talks from Unite'12. To get rid of them you

  1. either have to call Resources.UnloadUnusedAssets

  2. or change level

In your case you sya that you use Resources.UnloadUnusedAssets and load another level. So you use both of them and textures are not unloaded.

First of all why are you sure that textures are still there? Are you sure that this gameobject doesn't have don't destroy when loading another scene flag set? Are you sure that it is not referenced by any behavior with such flag?

Otherwise it looks like a bug.

Comment
Add comment · Show 1 · 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 Bugaga · Nov 07, 2012 at 03:01 PM 0
Share

I believe that changing scene and destroying the object doesn't make any difference. Only setting all references to null will allow you to get rid of texture.

Everybody can check this simple case on their own. Just output FindObjectsOfTypeAll(typeof(Texture2D)) to check if it's still there.

I understand how to deal with that problem. But it is really very unobvious and I hope to know why it happens.

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

11 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

Related Questions

why UnloadUnusedAssets doesn't unload a asset? 0 Answers

How can code generate memory garbage without instantiating any memory? 4 Answers

Unity Fatal error in gc: virtualalloc remapping failed 0 Answers

Out of memory loading between levels 1 Answer

Textrue2D is not cleaned after Apply(false,true) 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