"Turn" Unity Resource management Fundamentals knowledge (dry not too long)

Source: Internet
Author: User
Tags class definition shallow copy

Recent unity how to reduce memory when you need to create objects frequently. Here, 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 loading:
CreateFromFile from files (Note that this method can only be used for standalone programs) This is the fastest way to load
Can also come from memory, with Createfrommemory (byte ""), this byte "" can come from the file read buffer, www download or other possible way.
In fact, www assetbundle is the internal data read after the automatic creation of a assetbundle just
After 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, there is no concept of assets.

Assets Loading:

With Assetbundle.load (same resources.load) This will read and create a asset object from the Assetbundle memory image, and the asset object will also be allocated with the corresponding memory for storage (deserialization)
Asynchronous read with Assetbundle.loadasync
You can also read multiple Assetbundle.loadall

Release of Assetbundle:

Assetbundle.unload (flase) is a memory image that releases Assetbundle files and does not contain asset memory objects created by load.
Assetbundle.unload (True) is to release that assetbundle file memory image and destroy all asset memory objects created with load.
A prefab from the assetbundle. Inside may include: gameobject transform mesh texture material shader script and various other assets.

You instaniate a prefab, is a assets clone (copy) + reference combination of the process, Gameobject transform is clone is a new generation. Other Mesh/texture/material/shader, some of which are purely reference relationships, include: texture and terraindata, as well as references and replication, including: Mesh/material/ Physicmaterial. The referenced asset object is not copied, just a simple pointer to the asset object that has already been load. This vague reference-plus-clone mix is probably the main reason to confuse most people.

Specifically to mention is a special thing: script Asset, looks strange, unity in each script is a closed class definition, and did not write the calling code, the definition of light class script is not working. In fact, the unity engine is the calling code, clone a script asset equals the new class instance, the instance will finish the work. Hang him in the call chain of the unity main thread, and the OnUpdate OnStart in the class instance 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. In the process of new class, the data area is copied, and the code area is shared, which is a special copy + reference relationship.
You can instaniate a similar prefab, or this set of Mesh/texture/material/shader ..., this time there will be a new gameobject, etc., but will not create a new reference object 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 the use of these assets, these assets become no reference to the free data block, is unusedassets, this time can be released through the Resources.unloadunusedassets, Destroy cannot complete this task, Assetbundle.unload (false), Assetbundle.unload (true) can but is not safe unless you know 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 uses:

Assetbundle.createfrom ..... : Create a Assetbundle memory image and note that the same Assetbundle file cannot be used again until it is unload
WWW.AssetBundle: Ditto, of course, the first new one and then yield return before you can use
Assetbundle.load (name): reads a asset of the specified name from the Assetbundle and generates a asset memory object, if multiple Load objects of the same name are returned, except for the first time, only the asset objects that have been generated. That is, multiple load a asset does not generate more than one copy (singleton).
Resources.load (Path&name): Ditto, just load 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 there will never be automatic replication (unless you really need to implement copy with your code), it will only be

Creating and adding 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 be assetbundle.unload before it is 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
The differences between several dynamic load prefab modes of Unity:
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?

Image: P12.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's asset,instantiate is Gameobject and object in Scene
The asset of load should be unload,new or instantiate object can be destroy

Memory management Unity3d in Unity 3D has been criticized for its memory footprint, especially for mobile-oriented game development, with a high memory footprint of one hundred or two hundred trillion, resulting in the exhaustion of memory resources, resulting in a very poor experience of system retreat. Such a situation is not uncommon, but most of them can be avoided. While in theory Unity's memory management system should be a burden for developers to engage in more meaningful things, but for unity on how memory is managed, the official document does not have much to explain, the basic need to rely on their own exploration. There have been serious memory problems in the projects that have been taken over recently, and after much speculation and confirmation from the reference document and unity answer, a little summary of the basic ways of allocating and managing memory in unity is shared here.
While unity advertises that its memory usage is all "Managed memory", in fact you have to use it correctly to ensure that the recycling mechanism runs correctly. If you don't do what you have to do, the scenarios and code are likely to cause a lot of unnecessary memory usage, which is why many unity developers complain that memory usage is too high. Next I will describe the kind of memory that Unity uses, and the techniques for optimizing and using each of these types. By following the usage guidelines, you can allow non-essential resources to be released as quickly as possible, thereby reducing memory consumption.

The kind of memory in unity there are actually three types of memory used in Unity Games: program code, managed heap (Managed heap), and native heap (Native heap).
The program code includes all of the Unity engines, the libraries used, and all the game code you've written. After compiling, the resulting run file will be loaded into the device to execute and occupy a certain amount of memory.
This part of the memory is actually no way to "manage", they will be in memory from the beginning to the end of the existence. An empty unity default scene, what code is not put on the iOS device to occupy memory should be around 17MB, and add some of their own code can easily go up to about 20MB. To reduce the use of this part of memory, you can do is to reduce the use of the library, later.
The managed heap is part of the memory that is used by mono. Mono Project an open-source. NET Framework is an implementation that, for unity development, actually serves as the basic class library role.
The managed heap is used to hold instances of the class (such as a list generated with new, various declared variables in the instance, and so on). "Managed" means that mono "should" automatically change the size of the heap to fit the memory you need,
and periodically use garbage collection (garbage Collect) to free up memory that is no longer needed. The point is, sometimes you forget to clear references to memory that you don't need to use anymore.
This causes mono to think that this memory is always useful and cannot be recycled.
Finally, the native heap is where the unity engine applies and operates, such as stickers, sound effects, level data, and so on. Unity uses its own set of memory management mechanisms to make this memory feature similar to the managed heap.
The basic idea is that if you need a resource in this level, load it when you need it, and then unload it without any references. It sounds nice. And like the managed heap,
But because unity has a set of mechanisms for automating the loading and unloading of resources, it makes a big difference. Automatically loading resources can save a lot of money for developers,
But it also means that the developer loses the power to manually manage the loaded resources, which can easily lead to a lot of memory usage (maps or something you know),
It is also the culprit that unity gives people the impression of "eating memory".


Optimizer code memory footprint This part of the optimization is relatively simple, because there is not much to do: The main thing is to reduce the packaging of the reference library, change the build settings.
There's no big problem with a new project, but if it's an existing project, it's likely that the change will lead to a missing library (though it's generally unlikely),
Therefore, it may not be optimal.

When using unity development, the default mono include library can be said to be largely unused, in the player Setting (Edit->project Setting->player or Shift+ctrl (Command) + B in the Player setting button)
Panel, the "Api compatibility level" in the bottom optimization column is selected as. NET 2.0 subset, which means that you will only use the. NET 2.0 subset of the section, There is no need for unity to include all of the. NET APIs. The next "stripping level" represents the force stripped from the build's library, and each stripping option removes a portion of the content from the packaged library. You need to make sure that your code doesn't use this part of the stripped feature,
If you choose "Use Micro mscorlib" the smallest library will be used (generally no problem, you can try the previous two). Library stripping can greatly reduce the size of the packaged program and the memory footprint of the program code, the only drawback is that this feature only supports the pro version of Unity.
This part of the optimization effort needs to be based on the code. NET function to make adjustments, it may not be possible to use subset or the maximum peel strength.
If the limit is exceeded, it is likely that the feature will be crash if it is not found (iOS is likely to get an error when Xcode compiles).
A better solution is to still use the strongest stripping, complemented by a smaller third-party class library to complete the required functionality.
One of the most common problems is that Sysytem.xml is not supported by subset and micro at maximum stripping, and if it is just for XML, you can import a lightweight XML library to resolve dependencies (this is officially recommended by Unity).
A detailed list of the supported libraries for each setting can be found here. Unity's documentation also explains what each peel level does.
In fact, the vast majority of stripped-down features in game development are not used, so the optimization method of library stripping is worth a try anyway.


Managed heap Optimization Unity has a good description of how managed heap code is written, and I have some personal additions on that basis.
The first thing you need to make clear is that the memory stored in the managed heap is what you're applying for in your code (whether it's written in js,c# or boo).
In general, there is nothing more than a new or instantiate two method of generating an object (in fact instantiate also calls new).
After receiving the ALLOC request, the managed heap allocates memory on top of the object instance to be newly generated and its instance variables, and requests more space from the system if there is not enough free space.
When you have finished using an instance object, there is usually no reference to the object in the script (this includes setting the variable to null or another reference, beyond the scope of the variable,
or send Destory () to the Unity object. At intervals, mono's garbage collection mechanism detects memory and frees up memory that is no longer referenced. Overall
All you have to do is get rid of the unwanted references at the earliest possible time so that the recycling mechanism can properly clean up the memory that is not needed. However, it is important to note that the memory cleanup may cause the game to stutter for a short time,
This will have an impact on the gaming experience, so if you have a lot of memory recycling work to do, try to choose the right time.
If there are very many similar instances in your game, and you need to send destroy () to them often, the game performance will be pretty ugly. For example, the little bear pushes gold coins in the example, it is said that each gold coin behind the table
All need to Destory (), and then new gold coins to enter the table and need to instantiate, which is a great waste of performance. A common practice is to not destroy the gameobject when it is not needed, but to hide it,
And put it in a reusable array. Then, when needed, the available instances are found and displayed from the reuse array. This will greatly improve the performance of the game, the corresponding cost is to consume some memory, which is generally acceptable.
For object reuse, you can refer to the Reusable Object pools section of unity's memory-related documentation, or Prime31 have a video tutorial that uses LINQ to create a reuse pool (Youtube, which requires FQ, up, down).
If not necessary, the instantiate () and destroy () calls to Gameobject should be minimized in the course of the game, as there will be significant depletion of the compute resources. Mass generation and destruction of objects on portable devices for a short time
, it is easy to cause instant lag. If the memory is not a problem, try to collect them first and then destroy them in bulk and reclaim the memory at the right time (for example, by pressing the pause key or the level switch). Mono's memory recovery is done automatically in the background, and the system chooses the right time for garbage collection. At the right time, you can also manually call System.GC.Collect () to suggest that the system do a garbage collection.
It is important to note that the call here is really just a suggestion, that the system may be recycled after a period of time, or it may be completely disregarded, but for the most part, the call is reliable.


Optimization of the native heap when you load a unity scene, all the asset used in the scene (including materials, textures, animations, sounds, and so on are all gameobject on the hierarchy and in the script),
Will

"Turn" Unity Resource management Fundamentals knowledge (dry not too long)

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.