Memory Management in Unity 3D
Unity3d in memory occupied has been criticized, especially for mobile device game development, prone to memory consumption of one hundred or two hundred trillion megabytes, resulting in the exhaustion of memory resources, resulting in the system strong retreat resulting in a very poor experience. 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.
types of memory in Unity
Actually, there are 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 wrote. 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 heap size 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 that sometimes you forget to clear references to memory that you don't need to use anymore, causing mono to think that this memory is always useful and not recyclable.
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. It's the same as the managed heap, but because unity has a set of mechanisms for automating the loading and unloading of resources, it makes a big difference. Loading resources automatically can save a lot of money for developers, but it also means that developers lose the power to manually manage and load resources, which could easily lead to a lot of memory usage (maps or something you know), and unity gives people the "memory-eating" impression.
Memory footprint of Optimizer code
This part of the optimization is relatively simple, because there are not many things to do: The main thing is to reduce the packaging of the reference library, change the build settings. There is not much problem with a new project, but if it is an existing project, it is possible that the change will result in a missing library (though generally unlikely), so 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, select the "Api compatibility level" in the bottom optimization column as. NET 2.0 subset, indicating that you will only use the partial. NET 2.0 subset, 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 ensure that your code does not use this part of the stripped function, select "Use Micro mscorlib" will be used to the smallest library (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, exceeding the scope of the variable, or sending Destory () to the Unity object). At intervals, mono's garbage collection mechanism detects memory and frees up memory that is no longer referenced. In general, all you have to do is to get rid of unwanted references in as early a time as possible so that the recycling mechanism can properly clean up the memory that is not needed. However, it is important to note that there may be a short time lag in memory cleanup, which will affect the game 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 small bear to push gold coins in the case, it is said that each gold coin after the table will need to destory (), and then the new coins into 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 simply to hide it and put it into 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. It is easy to create and destroy objects on portable devices for short periods of time, causing 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 be automatically loaded (that's where Unity's intelligence is). That is, when the level is present in front of the user, all the Unity Editor can recognize the level of the resources have been pre-added memory, so in this level, the user will have a good experience, whether it is to change the map, sound, or play the animation, there will be no additional loading, The cost of this is that memory consumption will become much more. Unity was originally designed to be desktop-facing, with almost unlimited memory and virtual memory making it seem like no problem, but such a memory strategy has been a disadvantage in the rise of mobile platforms and the production of a large number of mobile devices, because the resources available to mobile devices are always very limited. Therefore, in the production of mobile device game, as far as possible to reduce the direct reference to resources in the hierarchy, but the use of Resource.load method, when needed to read from the hard disk resources, after use with Resource.unloadasset () and Resources.unloadunusedassets () to unload it as soon as possible. In short, here is a processing time and occupy memory space of trade off, how to achieve the best results without standard answers, need to weigh themselves.
At the end of the level, all the resources used in this level will be unloaded (unless Dontdestroyonload is flagged). Note that not only is the resource itself dontdestroyonload, but all its related resources are not unloaded when the level is switched. Dontdestroyonload are generally used to store some player's state between levels, such as fractions, levels, and other biased text messages. If Dontdestroyonload has a lot of resources (such as a large number of stickers or sound, such as large memory consumption of things), this part of the resources in the scene switch cannot unload, will always occupy memory, this should be avoided.
Another thing to note is the reference to the resource in the script. Most scripts will be invalidated and recycled when the scene is converted, but the script that is held between scenes is not included (typically, it is attached to the Dontdestroyonload gameobject). These scripts are likely to contain references to other objects ' component or resources, so that the associated resources are not released, which is definitely not the case. In addition, the static singleton (singleton) is not destroyed when the scene is switched, and similarly, if the singleton contains a large number of references to resources, it can also be a big problem. Therefore, it is necessary to minimize the coupling of the Code and the reliance on other scripts. If this is not the case, you should manually call destroy () or set it to NULL for those reference objects that are no longer in use. This allows the memory to be recycled when garbage collection is considered useless.
It is important to note that when unity starts at a scene, the resources that are automatically read based on the scene composition and reference relationships are cleaned only when a new scene is read or the current scene of the reset. So this part of the memory footprint is unavoidable. In a small memory environment, this part of the initial memory footprint is important because it determines whether your level can be loaded properly. Therefore, when there is sufficient computing resources or the opportunity to load after the level starts, minimizing references in hierarchy to manual resource.load will greatly reduce memory footprint. At Resource.unloadasset () and Resources.unloadunusedassets (), only those resources that really do not have any references to them are recycled, so make sure that when the resources are no longer in use, Set all references to this resource to null or destroy. It is also important to note that these two unload methods are only valid for the resources that Resource.load get, not the resources that are automatically loaded at the start of any scenario. Similar to the Assetbundle load and unload approach, the flexibility to use these manual, voluntary loading and unloading methods is the perfect rule for optimizing unity memory Footprint ~
Memory Management in Unity 3D