Comprehensive Understanding of Unity loading and Memory Management

Source: Internet
Author: User

There are two dynamic loading mechanisms in unity: resources. Load and assetbundle. In fact, there is no difference between the two in essence. Resources. load is to load resources from the assetbundle in the program package by default. Generally, the assetbundle file needs to be created by yourself and dynamically loaded during runtime. You can specify the path and source.

In fact, all static objects in the scenario also have such a loading process, but the unity background automatically completes for you.

Details:
Load assetbundle during runtime:
Createfromfile is used for files (note that this method can only be used for standalone programs). This is the fastest loading method.
You can also use createfrommemory (byte []) from memory. This byte [] can be a buffer for file reading, WWW download, or other possible methods.
Actually, the assetbundle of WWW is an assetbundle automatically created after the internal data is read.
After the create operation, a file on the hard disk or network is read to the memory area. This is only an assetbundle memory image data block and there is no assets concept.
Assets loading:
Use assetbundle. load (same as resources. this will read from the memory image of assetbundle and create an asset object. When creating an asset object, the corresponding memory will be allocated for storage (deserialization)
Assetbundle. loadasync for asynchronous reading
You can also read multiple instances at a time using assetbundle. loadall
Release assetbundle:
Assetbundle. Unload (flase) is the memory image for releasing the assetbundle file, excluding the asset memory object created by load.
Assetbundle. Unload (true) is to release the memory image of the assetbundle file and destroy all asset memory objects created with load.

A prefab load from assetbundle may include: gameobject transform mesh texture material shader script and various other assets.
You instantiate a prefab, which is a process of cloning (copying) and referencing the assets. The gameobject transform is generated by cloning. Other mesh/texture/material/shader, some of which are purely referenced, including texture and terraindata, as well as the coexistence of reference and replication, including: mesh/material/physicmaterial. The referenced asset object will not be copied, but a simple pointer points to the loaded asset object. This vague reference and clone mix is probably the main reason for confusing most people.
Specifically, I want to mention a special thing: script asset, which looks strange. Every script in unity is a closed class definition and does not write the call code, the definition script of the light class will not work. In fact, the Unity engine is the calling code. clone a script asset to a new class instance to complete the work. Mount it to the call chain of the main unity thread, and onupdate onstart in the class instance will be executed. When multiple objects are mounted to the same script, they are actually mounted to multiple instances of the script class on multiple objects. This is easy to understand. In the new class process, the data zone is replicated, and the code zone is shared. This is a special copy + reference relationship.
You can instantiate the same prefab, or this set of mesh/texture/material/shader.... At this time, there will be new gameobject, but no new referenced objects such as texture will be created.
So the assets you load out are actually a data source used to generate new objects or be referenced. The generated process may be copying (clone) or referencing (pointer)
When you destroy an instance, only the clone objects are released, and the referenced objects and clone data source objects are not released. Destroy does not know whether other objects are referencing those objects.
When no game scene object is using these assets, these assets become unreferenced free data blocks, which are unusedassets. At this time, you can use resources. unloadunusedassets to release, destroy cannot complete this task, assetbundle. unload (false) does not work either, assetbundle. unload (true) is acceptable but insecure, unless you know that no object is using these assets.
Although all of them are called asset, copying and referencing are different. This is covered by the dark technical details of unity and needs to be understood by yourself.

About Memory Management
According to the traditional programming thinking, the best way is to maintain all the objects by yourself, use a queue to save all the objects, the destory is not used, and the unload is processed by yourself.
However, it is unnecessary and troublesome under the C #. NET Framework.
You can manage it in this way.

At creation:
Create an assetbundle, whether from www, file or memory
Use assetbundle. Load to load the required asset
After loading, assetbundle. Unload (false) immediately releases the memory image of the assetbundle file, but does not destroy the loaded asset object. (In this way, you do not need to save the assetbundle reference and can immediately release some memory)

Release:
If an instantiate object exists, use destroy to destroy it.
Call resources. unloadunusedassets in the appropriate place to release the unreferenced asset.
If you need to immediately release the memory with GC. Collect (), otherwise the memory may not be immediately released, sometimes leading to excessive memory usage and exception.
This ensures that the memory is always released in time and occupies the least amount. You do not need to reference each loaded object.

Of course, this is not the only method. As long as the load and release principles are followed, any method is acceptable.

When the system loads a new scenario, all the memory objects will be automatically destroyed, including the objects you have loaded with assetbundle. load and the cloned instaniate. But it does not include the memory image of the assetbundle file itself. It must be released with unload. In. net terms, this data cache is not hosted.

Summarize the usage of various loading and initialization methods:
Assetbundle. createfrom...: creates an assetbundle memory image. Note that the same assetbundle file cannot be used again before unload.
Www. assetbundle: Same as above. Of course, you must first create one and then return yield before using it.
Assetbundle. load (name): read an asset with the specified name from assetbundle and generate an asset memory object. If you load an object with the same name multiple times, only the generated asset object will be returned except for the first time, that is to say, loading an asset multiple times does not generate multiple copies (Singleton ).
Resources. Load (Path & name): Same as above. It is only loaded from the default position.
Instantiate (object): Clone the complete structure of an object, including all its component and sub-objects (see the official documentation for details). Do not copy all reference types. There is a special usage. Although it is rarely used in this way, you can use instantiate to completely copy a reference type asset, such as texture, the texture to be copied must be of the read/write type.

Summary of various releases
Destroy: it is mainly used to destroy a cloned object. It can also be used for static objects in a scenario and will not automatically release all references to the object. Although it can also be used for asset, be careful when the concept is different. If it is used to destroy an asset object loaded from a file, it will destroy the corresponding resource file! However, if the destroyed asset is copied or dynamically generated using a script, only the memory object will be destroyed.
Assetbundle. Unload (false): releases the memory image of the assetbundle file.
Assetbundle. Unload (true): releases the memory image of the assetbundle file and destroys all loaded assets memory objects.
Reources. unloadasset (object): explicitly releases the loaded asset object. Only the asset object loaded by the disk file can be detached.
Resources. unloadunusedassets: Used to release all asset objects that are not referenced.
GC. Collect () force the Garbage Collector to immediately release the memory. The GC function of unity is not good. If you are unsure, force the call.

Before 3.5.2, it seems that unity cannot release the asset explicitly.

Here are two examples to help you understand
Example 1:
A common error: You load a prefab from an assetbundle and clone it: OBJ = instantiate (assetbundle1.load ('myprefab ");
This prefab is like an NPC.
Then you used destroy (OBJ) when you didn't need it. You thought it would be enough to release it.
In fact, at this time, only the clone object is released. All referenced and non-referenced assets objects loaded by load are quietly lying in the memory.
In this case, use assetbundle1.unload (true) after destroy to completely release the package.
If this assetbundle1 is inconvenient for unload reading repeatedly, you can use: resources. unloadunusedassets () to destroy all assets related to this NPC after destroy.
Of course, if this NPC is frequently created and destroyed, we should keep those assets in memory to accelerate the gaming experience.
This explains another topic that someone mentioned earlier: Why does one get stuck when instantiate a prefab for the first time? Because before you instantiate for the first time, the corresponding asset object has not been created yet, to load the built-in assetbundle of the system and create assets, after the first time, although you destroy, the assets objects of prefab are still in the memory, so it is very fast.

Example 2:
Reads A 1. unity3d file from the disk to the memory and creates an assetbundle1 object.
Assetbundle assetbundle1 = assetbundle. createfromfile ("1. unity3d ");
Read and create a texture asset from assetbundle1 and point the main Paster of obj1 to it.
Obj1.renderer. Material. maintexture = assetbundle1.load ("wall") as texture;
Point the main Paster of obj2 to the same texture asset.
Obj2.renderer. Material. maintexture = obj1.renderer. Material. maintexture;
Texture is a reference object and will never be automatically copied (unless you really need it, use your own code to copy it). It will only create and add references.
If you continue:
Assetbundle1.unload (true), both obj1 and obj2 become black, because the texture asset to be pointed to is gone.
If:
Assetbundle1.unload (false) does not change the values of obj1 and obj2, but the memory image of assetbundle1 is released.
Continue:
Destroy (obj1), // The obj1 is released, but the texture of the load is not released.
If at this time:
Resources. unloadunusedassets ();
No memory will be released because texture asset is still used by obj2
If
Destroy (obj2)
Obj2 is released, but the texture of the load is not released.
Continue
Resources. unloadunusedassets ();
At this time, the load texture asset is released, because there is no reference
Last CG. Collect ();
Force immediate release of memory
This can lead to another question raised several times in the Forum.
Without considering assetbundle, If you directly use WWW to read image files, a texture asset is directly created.
Assume that 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 the memory, and the Code does not need to trace the last loaded texture asset, but the speed is relatively slow.
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 );
}
This allows fast uninstallation.

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.