Unity3d a solution that takes up too much memory

Source: Internet
Author: User

Original link: http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html

Recently the Netizen searches through the website Unity3d in the handset and other platform to occupy the memory too big . Write about Unity3d for memory management and optimization .

There are two kinds of dynamic loading mechanism in Unity3d: one is resources.load, the other is Assetbundle, but the difference is not very big. Resources.load is from a default into the package Assetbundle loading resources, and general assetbundle files need you to create, run-time dynamic loading, you can specify the path and source.

In fact, all the static objects in the scene have such a loading process, just unity3d the background for you automatically completed.

Elaborate on the concept of detail:
Assetbundle Run-time load:
It's from the file.CreateFromFile (Note that this method can only be used forStandalone program) This is the fastest way to load
can also come fromMemory, withCreatefrommemory (byte[]), thisByte[] can come from a file read buffer,www downloads or other possible ways.
In factWWW'sAssetbundle is the internal data is read after the automatic creation of aAssetbundle.
After the Create is equal to the hard disk or the network of a file read into an area of memory, this time is just a assetbundle memory image data block, not assets.
Assets load :
assetbundle.load (same resources.load)   This will read and create a lang= >assetbundle "en-us" from the memory image of asset object also allocates the corresponding memory to hold (deserialization Asynchronous read with assetbundle.loadasync
can also read multiple releases with assetbundle.loadall
Assetbundle at one time:
Assetbundle.unload (flase) is a memory image that releases assetbundle files and does not contain The asset memory object created by load.
Assetbundle.unload (True) is to release that assetbundle file memory image and Destroy all load created asset memory objects.

OnePrefab fromAssetbundle.The load may include:Gameobject Transform mesh Texture material shader script and various otherAssets.
YouInstaniate APrefab, is a pair ofAssets toClone (copy) + Refer to the combined process,Gameobject Transform isClone is a new build. OtherMesh/texture/material/shader, some of which are purely reference relationships, include:Texture andTerraindata, as well as references and replication, are also available, including:Mesh/material/physicmaterial. Referenced byThe asset object will not be copied, just a simple pointer pointing to an alreadyLoad'sThe asset object. This vague reference-plus-clone mix is probably the main reason to confuse most people.
Specifically to mention is a special thing:Script Asset, it looks strange,Unity in everyThe script is a closedClass definition., and did not write the calling code, the lightThe definition script for class is not working. ActuallyThe Unity engine is the calling code,Clone aScript Asset equalsNew OneClass instance, the instance will not complete the work. Hang him up.In the call chain of the unity main thread,In the class instance.OnUpdate OnStart and so on will be executed. More than one object hangs the same script, in fact, it is to hang the multiple instances of the script class on more than one object, so it is understandable. InIn this process, the data area is copied, the code area is shared, and is a special kind of replication+ Reference relationship.
You can thenInstaniate one of the samePrefab, or is this setMesh/texture/material/shader, there will be a newGameobject, but does not create new reference objects such as Texture.
So the assets that you load is actually a data source that is used to generate new objects or to be referenced, and the resulting process might be a copy (clone) or a reference (pointer)
When you destroy an instance, just release those clone objects and do not release the data source object that references the object and clone,destroy does not know if there are any other objects that reference them.
Wait until there is no game scene object after using these assets, these assets become the free data block without reference, is unusedassets, this time can pass Resources.unloadunusedassets to release , destroy can not complete this task,Assetbundle.unload (false) also not,Assetbundle.unload (true) can, but is not safe, unless you are aware that no object is using these assets.
With a picture to deepen understanding:

Unity3d memory is too large how to solve it?

Although called asset, the copy and the reference are not the same, this is masked by unity's dark technical details, need to understand.

About Memory management
According to the traditional programming thinking, the best way is to maintain all the objects, with a queue to save all the object, not when the destory, the unload's own processing.
But this is a bit unnecessary and cumbersome under the C #. NET Framework.
On the safe side, you can manage that.

When created:
First build a assetbundle, whether from www or file or memory
Load the required asset with Assetbundle.load
Immediately after loading, Assetbundle.unload (false) releases the memory image of the Assetbundle file itself, but does not destroy the loaded asset object. (so you don't have to save the Assetbundle reference and you can immediately release a portion of the memory)
When released:
If there are instantiate objects, destroy them with destroy.
Call Resources.unloadunusedassets at the appropriate place to release the asset that have not been referenced.
If you need to free memory immediately plus gc.collect (), memory may not be released immediately, sometimes causing excessive memory consumption and throwing an exception.
This ensures that the memory is always released in a timely manner, taking the least amount. There is also no need to reference each loaded object.

This is not the only way, of course, as long as you follow the principle of loading and releasing, anything can be done.

When the system loads a new scene, all the memory objects are automatically destroyed, including the objects you loaded with Assetbundle.load and the Instaniate clones. But it does not include the memory image of the Assetbundle file itself, which must be freed with unload, and in. NET terms, this data cache is unmanaged.

Summarize the various loading and initialization usages:
Assetbundle.createfrom ..... : Create a Assetbundle memory image, noting that the same Assetbundle file cannot be used again
WWW before it is unload. Assetbundle: Ditto, of course, you must first new one yield return before you can use
Assetbundle.load (name): reads a asset of a specified name from Assetbundle and generates asset memory objects. If multiple load objects have the same name, only the asset objects that have been generated will be returned except for the first time, that is, multiple load one asset does not generate more than one copy (singleton).
Resources.load (path&name): Same as above, just loaded from the default location.
Instantiate (object): Clone a complete structure of an object, including all its component and sub-objects (see official documentation), shallow copy, and does not copy all reference types. There is a special usage, although rarely used, in fact, can be used instantiate to complete the copy of a reference type of asset, such as texture, to copy the texture must be type set to read/write able.

Summarize the various releases
Destroy: Used primarily for destroying cloned objects or for static objects within a scene, and does not automatically release all references to the object. Although it can also be used for asset, the concept is not as careful if the asset object that is used to destroy the load from the file destroys the corresponding resource file! However, if the destroyed asset is copy or dynamically generated with a script, only the memory object will be destroyed.
Assetbundle.unload (FALSE): Release Assetbundle file memory image
Assetbundle.unload (TRUE): Releases Assetbundle file memory image while destroying all assets memory objects that have already been load
Reources.unloadasset (object): explicitly releasing loaded asset objects, only unloading asset objects loaded by the disk file
Resources.unloadunusedassets: Used to release all asset objects that are not referenced
Gc. Collect () force garbage collector to release memory immediately Unity's GC function is not good, and when you're not sure, force a call.

Before 3.5.2, it was like unity couldn't explicitly release asset.

Give two examples to help understand
Example 1:
A common mistake: you Load a prefab from a assetbundle and clone it: obj = instaniate (assetbundle1.load (' Myprefab ');
This prefab, like a NPC.
And then you don't need him. You used: Destroy (obj); you thought you were free.
In fact, this time just released the Clone object, all the references loaded through load, non-reference assets objects all lie quietly in memory.
This situation should be used after destroy: Assetbundle1.unload (True), completely released cleanly.
If the AssetBundle1 is inconvenient unload to be read repeatedly, it can be used after destroy: Resources.unloadunusedassets () destroys all asset associated with the NPC.
Of course, if the NPC is to be frequently created and destroyed, then those assets should be kept in memory to speed up the gaming experience.
This can explain another topic that was previously mentioned: why the first time instaniate a prefab time will be stuck, because before your first instaniate, the corresponding asset object has not been created, to load the system built-in Assetbundle and create assets, the first time after you although destroy, but prefab assets objects are still in memory, so soon.

By the way, the difference between several loading methods:
There are actually 3 ways to load:
One is static reference, build a public variable, in the Inspector Prefab pull up, use when instantiate
The second is resource.load,load after instantiate
Three is assetbundle.load,load after instantiate
There are three ways to have the details difference, the first two methods, the reference object texture is loaded at instantiate, and Assetbundle.load will perfab all assets loaded, instantiate just to generate clone. So in the first two ways, unless you load the relevant reference object in advance, the first instantiate will contain the operation that loads the reference assets, causing the lag to load for the first time.

Example 2:
Reads a 1.unity3d file from disk into memory and builds a AssetBundle1 object
Assetbundle AssetBundle1 = Assetbundle.createfromfile ("1.unity3d");
Read and create a texture Asset from the AssetBundle1 and point the obj1 main map to it
Obj1.renderer.material.mainTexture = Assetbundle1.load ("Wall") as Texture;
The OBJ2 's main map also points to the same texture Asset
Obj2.renderer.material.mainTexture =obj1.renderer.material.maintexture;
Texture is a reference object and will never have automatic replication (unless you really need to implement copy with your code), just create and add references
If you continue:
Assetbundle1.unload (True) that obj1 and obj2 all turned black, because the texture asset to the point was gone.
If:
Assetbundle1.unload (false) that obj1 and obj2 do not change, just the memory image of AssetBundle1 is released
Go on:
Destroy (OBJ1),//obj1 is released, but does not release the texture of the load just now
If this is the case:
Resources.unloadunusedassets ();
There will be no memory release because texture asset is still being used by OBJ2.
If
Destroy (OBJ2)
Obj2 is released, but will not release the texture of the load just now.
Go on
Resources.unloadunusedassets ();
This time the load texture asset was released because there was no reference to the
Last Cg.collect ();
Force immediate free memory
This can be derived from the forum of another has been raised a few questions, how to load a large number of pictures in turn show do not explode
Do not consider assetbundle, directly with the WWW read the picture file is equal to directly created a texture Asset
Suppose the file is saved in a list.
Tllist<string> fileList;
int n=0;
IEnumerator OnClick ()
{
www image = new www (filelist[n++]);
yield return image;
Obj.maintexture = image.texture;

n = (n>=filelist.length-1)? 0:n;
Resources.unloadunusedassets ();
}
This ensures that there is always only one giant texture Asset resource in memory and no code to track the last loaded texture Asset, but slower
Or:
IEnumerator OnClick ()
{
www image = new www (filelist[n++]);
yield return image;
Texture tex = obj.maintexture;
Obj.maintexture = image.texture;

n = (n>=filelist.length-1)? 0:n;
Resources.unloadasset (Tex);
}
It's faster to unload

Hog's comments Quote:

Feel this is the place where unity memory management is dark and chaotic, especially involved in texture
I have also been testing these recently with Assetbundle loaded asset can be uninstalled with resources.unloadunusedassets, but must first assetbundle.unload, will be recognized as useless. Asset . the Safer Way is
When created:
First build a assetbundle, whether from www or file or memory
Load the required asset with Assetbundle.load
Assetbundle.unload (false) immediately after use, close assetbundle but do not destroy created objects and references
When destroyed:
Destroy the object of the instantiate
Call Resources.unloadunusedassets at the appropriate place to release the asset that have not been referenced.
If needed immediately release plus gc.collect ()
This will ensure that memory is always released in a timely manner.
As long as you unload the Assetbundle, those created objects and references will be automatically freed when Loadlevel.

A comprehensive understanding of unity loading and memory management mechanisms: further depth and detail
Unity differences in several dynamic loading prefab modes:
In fact there are 3 ways to load prefab:
One is static reference, build a public variable, in the Inspector Prefab pull up, use when instantiate
The second is resource.load,load after instantiate
Three is assetbundle.load,load after instantiate
There are three ways to have the details difference, the first two methods, the reference object texture is loaded at instantiate, and Assetbundle.load will perfab all assets loaded, instantiate just to generate clone. So in the first two ways, unless you load the related reference object in advance, the first instantiate will contain the operation that loads the reference class assets, causing the lag to load for the first time. Official Forum Some people say that resources.load and static references are pre-loaded for all resources, the results of repeated tests, static references and resources.load are also OnDemand, and will only be loaded when used.

Differences in how several assetbundle are created:
CreateFromFile: This way does not load the entire hard disk Assetbundle files into memory, but rather similar to the creation of a file operation handle and buffer, real-time load when needed, so this loading method is the most resource-saving, Basically assetbundle itself does not account for any memory, only the memory of the asset object is required. Unfortunately, it can only be used in Pc/mac standalone programs.
Createfrommemory and Www.assetBundle: In both ways assetbundle files are mirrored in memory, in theory the size of the file requires much memory, and then the load consumes additional memory to generate the asset object.

When is Unusedassets?
See an example:
Object obj = resources.load ("Myprefab");
Gameobject instance = Instantiate (obj) as gameobject;
.........
Destroy (instance);
The creation then destroys a prefab instance, when Myprefab has not been referenced by the actual object, but if:
Resources.unloadunusedassets ();
The memory is not released because Myprefab is also referenced by this variable, obj
This time
obj = null;
Resources.unloadunusedassets ();
So that you can really release the assets object
So: Unusedassets not only to be referenced by the actual object, but also not to be referenced by a variable in the life cycle, it can be understood as Unused (reference count is 0)
So: If you use a global variable to save your load's assets, and you don't explicitly set it to NULL, then you unloadunusedassets not be able to release those assets before the variable expires. If you assets are not loaded from disk, there is no other way to unload it except unloadunusedassets or loading a new scene.

A complex example, the code is ugly, and it's impossible to do that, just to deepen understanding.

IEnumerator OnClick ()

{

Resources.unloadunusedassets ();//clean to avoid affecting the test effect

Yield return new Waitforseconds (3);

float wait = 0.5f;

Using WWW to read a assetbundle, inside is a unity basic sphere and a material with a large map, is a prefab

www aa = new www (@ "file://SpherePrefab.unity3d");

Yield return AA;

Assetbundle asset = Aa.assetbundle;

Yield return new Waitforseconds (wait)//0.5s per step for easy analysis of results

Texture TT = asset. Load ("Balltexture") as texture;//loading map

Yield return new waitforseconds (wait);

Gameobject ba = asset. Load ("Sphereprefab") as gameobject;//load prefab

Yield return new waitforseconds (wait);

Gameobject obj1 = Instantiate (BA) as gameobject;//generation instance

Yield return new waitforseconds (wait);

Destroy (obj1);//Destroy Instance

Yield return new waitforseconds (wait);

Asset. Unload (false);//Unload Assetbundle

Yield return new waitforseconds (wait);

Resources.unloadunusedassets ();//unload useless resources

Yield return new waitforseconds (wait);

BA = null;//the prefab reference to empty after unloading the useless load resource

Resources.unloadunusedassets ();

Yield return new waitforseconds (wait);

tt = null;//unload useless resources after texture reference is empty

Resources.unloadunusedassets ();

}

This is the memory profile graph of the test results.

Unity3d memory is too large how to solve it ?

Picture :p 12.jpg

It's a classic symmetrical shape, with how much to release.

This is the memory and other data changes at each stage

Description
1 Initial state
2 after loading the Assetbundle file, the memory of the file image, the amount of increase, total object and assets increased by 1 (Assetbundle is also an object)
3 load texture, memory continues to rise, because more texture asset,total objects and assets increased by 1
4 after loading the prefab, there is no noticeable change in memory because the texture of memory is already loaded, materials is increased because of the prefab material, total objects and assets increased by 6, because Perfab contains many components
5 after instantiating prefab, the memory texture memory, gameobjecttotal, Objects in scene rise, all because a visual object is instantiated
6 After destroying the instance, restore the changes in the previous step, well understood
7 After uninstalling the Assetbundle file, the memory occupied by the Assetbundle file image is freed, and the corresponding assets and total Objects count are also reduced by 1
8 direct resources.unloadunusedassets, without any change, since all assets references are not emptied
9 after the prefab reference variable is set to NULL, the entire prefab has no references except texture, so it is unloadunusedassets destroyed, assets and total Objects count minus 6
10 The reference variable of texture is then set to NULL, then also destroyed by Unloadunusedassets, memory is freed, assets and total Objects count minus 1, basic restore to initial state

It can also be seen from:
Texture after loading is to memory, display the time to enter the memory of texture memory.
All things are based on object.
Load of Asset,instantiate is Gameobject and object in Scene
Load The asset to unload,new or instantiate object can be destroy

Unity3d a solution that takes up too much memory

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.