翻译:https://unity3d.com/cn/learn/tutorials/topics/best-practices/native-memory
在优化应用程序时,Native Memory是一个关键部分,因为大多数引擎代码位于常驻内存中。 当你在原生插件中集成代码时,你可以直接控制它,但是从 Unity 内部系统中控制和优化Native Memory消耗并不总是可能的。 内部系统使用不同的缓冲区和资源,它可能并不总是明显地影响内存消耗。 下面的部分详细介绍了 Unity 内部系统,并解释了您在Native Profiler中经常看到的内存数据。
Native Buffer
Unity 使用许多不同的本地分配器和缓冲区。 有些是持久性的,如常量缓冲区,而其他则是动态的,如后台缓冲区。 下面的子节描述了缓冲区及其行为。
Scratchpad
Unity 将常量存储在一个4mb 的缓冲池中,并在帧之间的缓冲池中循环。 该池在其生命周期内与 GPU 绑定,并显示在帧捕获工具中,如 XCode 或 Snapdragon。
Block allocator
Unity 在一些内部系统中使用块分配器。 在 Unity 需要分配新的页面内存块时,会有内存和 CPU 开销。 通常,页面的块大小足够大,以至于分配仅在 Unity 第一次使用系统时才出现。 在第一次分配之后,页面块将被重用。 内部系统使用块分配器的方式有细微的差别。
AssetBundles
第一次加载 AssetBundle 时,当块分配器运行时,需要额外的 CPU 和内存开销,从而允许 Asset Bundle 系统分配第一个页面内存块。
但是,如果您想同时加载许多Asset Bundles,Unity 会重用Asset Bundles系统分配的页面,那么您可能必须分配第二个或第三个块。 所有这些停留分配,直到应用程序终止。
Resources
Resources使用一个与其他系统共享的块分配器,因此在第一次从Resources加载Asset时不会有 CPU 或内存开销(正如之前在启动时所发生的那样)。
Ringbuffer
Unity使用一个环形缓冲区将纹理推送到GPU。 你可以通过QualitySettings.asyncUploadBufferSize来调整这个异步纹理缓冲区。 注意:Unity分配了Ring 缓冲区内存后,您不能将它返回到系统。
Assets
在运行时,资产会引起本机和托管内存问题。 除了托管内存之外,Unity 在不再需要时将本机内存返回到操作系统。 由于每个字节都很重要——尤其是在移动设备上——你可以尝试以下方法来减少本地运行时内存:
- 从网格中移除未使用的管道
- 从动画中删除多余的关键帧
- 在Quality Settings中使用 maxLOD 可以从构建中删除 LODGroups 中较高的细节网格
- 在构建之后检查 Editor.log,以确保磁盘上每个 Asset 的大小与其运行时内存使用成正比
- 通过使用质量设置渲染部分的纹理质量设置,通过 mipmap 强制降低纹理分辨率,从而减少上传到GPU内存的内存
- 法线贴图不需要与漫反射贴图(1:1)大小相同,因此您可以对法线贴图使用较小的分辨率,同时仍然实现高视觉保真度并节省内存和磁盘空间
请注意,由于托管堆的大量碎片,托管内存影响通常会超过本机内存问题。
Cloned Materials
谨防克隆材料,因为访问任何渲染器的材料属性都会导致材料被克隆,即使没有分配任何内容。 这个克隆材料不会被垃圾回收,只有在您更改 Scenes 或调用 Resources.UnloadUnusedAssets ()时才会被清除。 如果想访问只读材料,可以使用 customer.sharedmaterial。
Unloading Scenes
调用 UnloadScene ()来销毁和卸载与场景相关的游戏对象。 注意: 这不会卸载相关联的资产。 为了卸载资产并释放托管内存和本机内存,需要在卸载场景后调用 Resources.UnloadUnusedAssets ()。
Audio
1. Virtual Voices
Unity 根据平台的实时可听性,动态地将声音设置为虚拟或真实。 例如,Unity 设置了远距离或者低音量的声音作为虚拟声音,但是如果声音靠近或者变大,它就会把这些声音变成真实的声音。 音频设置中的默认值是移动设备的很好的值。
Max Virtual Voice Count | Max Real Voice Count | |
---|---|---|
Default | 512 | 32 |
Maximum | 4095 | 255 |
2.DSP Buffer Size
Unity 使用 DSP 缓冲区大小来控制混频器的延迟。 底层音频系统 FMOD 定义了与平台相关的 DSP 缓冲区大小。 缓冲区大小影响延迟,应该谨慎处理。 缓冲区的数量默认为4。 在 Unity 中的音频系统使用以下样例计数来设置 Unity 中的音频设置:
Latency = Samples * Number of Buffers | Samples | Number of Buffers |
---|---|---|
Default | iOS & Desktop: 1024 Android: 512 | 4 |
Best latency | 256 | 4 |
Good latency | 512 | 4 |
Best performance | 1024 | 4 |
Audio Import Settings
使用正确的设置可以节省运行时内存和 CPU 性能。
1.如果音频文件不需要立体声,则启用Force to mono选项; 这样做将减少运行时内存和磁盘空间。 这主要用于带有单声道扬声器的移动平台。
2.更大的音频片应该设置为Streaming。 在 Unity 5.0及以后版本中的流媒体开销为200KB,因此您应该将小于200KB 的音频文件设置为Compressed into Memory。
3.只有在内存充足但 CPU 性能有限的情况下才使用 Decompress On Load,因为这个选项需要大量的内存
各种平台也有首选的压缩格式设置,以节省运行时内存和磁盘空间:
1.设置压缩格式为 ADPCM 的非常短的剪辑,如声音效果,经常播放。 Adpcm 提供了一个固定的3.5:1压缩比,并且是廉价的减压。
2.在安卓系统上使用 Vorbis 进行更长的剪辑。 统一不使用硬件加速解码。
3.在 iOS 上使用 MP3或 Vorbis 播放更长的视频剪辑。 统一不使用硬件加速解码。
Mp3或 Vorbis 需要更多的解压资源,但提供更小的文件大小明显。 高质量的 mp3需要较少的解压缩资源,而中等质量和低质量的文件需要几乎相同的 CPU 时间进行解压缩。
提示: 使用 Vorbis 作为更长的循环声音,因为它处理循环更好。 Mp3包含预定大小的数据块,因此如果循环不是块大小的精确倍数,那么 MP3编码将增加沉默而 Vorbis 不。