在一个较为复杂的大中型项目中, 资源的内存占用往往占据了总体内存的70%以上. 因此, 资源使用是否恰当直接决定了项目的内存占用情况. 一般来说, 一款游戏项目的资源主要可分为如下几种: 纹理 ( Texture ) , 网格 ( Mesh ) , 动画片段 ( AnimationClip ) , 音频片段 ( AudioClip ) , 材质 ( Material ) , 着色器 ( Shader ) , 字体资源 ( Font ) 以及文本资源 ( Text Asset ) 等等. 其中, 纹理, 网格, 动画片段和音频片段则是最容易造成较大内存开销的资源.
具体资源优化应该注意的点:
对于目前绝大多数基于Unity引擎开发的项目而言, 其托管堆内存是由Mono分配和管理的. “托管” 的本意是Mono可以自动地改变堆的大小来适应你所需要的内存, 并且适时地调用垃圾回收 ( Garbage Collection ) 操作来释放已经不需要的内存, 从而降低开发人员在代码内存管理方面的门槛.
但是这并不意味着研发团队可以在代码中肆无忌惮地开辟托管堆内存, 因为目前Unity所使用的Mono版本存在一个很严重的问题, 即: Mono的堆内存一旦分配, 就不会返还给系统. 这意味着Mono的堆内存是只升不降的
引擎自身中存在内存开销的部分纷繁复杂, 可以说是由巨量的”微小” 内存所累积起来的, 比如GameObject及其各种Component ( 最大量的Component应该算是Transform了 ) , ParticleSystem, MonoScript以及各种各样的模块.
一般情况下, 上面所指出的引擎各组成部分的内存开销均比较小, 真正占据较大内存开销的是这两处: WebStream和SerializedFile. 其绝大部分的内存分配则是由AssetBundle加载资源所致.
当某资源脱离了监控, 在本该释放的情境下没有释放掉, 我们可以认为发生了”内存泄露”. 导致这种情况的原因可以是:
正如上文提到的, Mono的堆内存一旦分配, 就不会返还给系统. 这意味着Mono的堆内存是只升不降的. 因此我们应该:
所谓“资源冗余”, 是指在某一时刻内存中存在两份甚至多份同样的资源. 导致这种情况的出现主要有:
meshRender.material
的参数, 因此 Unity引擎会实例一份新的Material
来达到效果, 进而造成内存上的冗余两种模式: Simple(每一帧实时更新)和Detailed(通过采样获得某一帧的详细数据)
Simple
The Simple view shows a simple overview how memory is used throughout Unity in real-time on a per-frame basis.
Unity reserves memory pools for allocations in order to avoid asking the operating system for memory too often. This is displayed as a reserved amount, and how much is used.
The areas covered by this are:
- Unity The amount of memory tracked by allocations in native Unity code
- Mono The total heap size and used heap size used by managed code. This memory is garbage-collected
- GfxDriver The estimated amount of memory the driver is using on Textures, render targets, Shaders and Mesh data.
- FMOD The Audio driver’s estimated memory usage
- Profiler Memory used for the Profiler data
Detailed
The Detailed view allows you take a snapshot of the current state. Use the Take Sample button to capture detailed memory usage. Obtaining this data takes some time, so the Detailed view should not be expected to give you real-time details. After taking a sample, the Profiler window is updated with a tree view where you can explore memory usage.
This displays individual Assets and GameObject memory usage. It also displays a reason for a GameObject to be in memory. Common reasons include:
- Assets: Asset referenced from user or native code
- Built-in Resources: Unity Editor resources or Unity default resources
- Not Saved: GameObjects marked as DontSave
- Scene Memory: GameObject and attached components
- Other: GameObjects not marked in the above categories
可以提供所有由 Unity 分配的 C++ 对象的内存信息, 在该工具内被称为 NativeUnityEngineObject
(Native-only Mode). 当 C# 脚本经由 il2cpp 编译为 C++ 时, 此工具可以提供额外的所有 C# 对象的信息, 在该工具内被称为 ManagedObject
(Full Mode).
Unity 5.3a4 has a new very lowlevel memory profiler API. It can tell you which objects got blamed for how much C++ memory allocations. On IL2CPP and Mono .NET 3.5 platforms, it will also give you a dump of the entire C# heap, as well as C# type descriptions.
参考文章: