# Unity 中的内存

> Manage and optimize memory usage in Unity applications.


**Frame:**
![](/api/media?file=/engine/6000.0/media/images/memory-in-unity-header.jpg)

为确保应用程序在运行时没有性能问题，必须了解 Unity 如何使用和分配内存。本文档的这一部分将介绍内存在 Unity 中的工作方式，面向希望了解如何提高应用程序内存性能的读者。

Unity 使用三个内存管理层来处理应用程序中的内存：

* [托管内存](#managed-memory)：一个受控内存层，使用托管堆和[垃圾收集器](https://en.wikipedia.org/wiki/Garbage_collection_\(computer_science\))来自动分配和指定内存。
* [C# 非托管内存](#unmanaged-memory)：可与 Unity Collections 命名空间和包结合使用的内存管理层。此内存类型称为“非托管”，因为它不使用[垃圾收集器](/engine/6000.0/manual/analysis/performance-memory-overview/managed-memory/garbage-collector.md)来管理未使用的内存部分。
* [本机内存](#native-memory)：Unity 用于运行引擎的 C++ 内存。在大多数情况下，Unity 用户无法访问此内存，但如果要微调应用程序性能的某些方面，了解此内存将有所帮助。

## 托管内存

[Mono 和 IL2CPP 的](/engine/6000.0/manual/scripting/compilation-and-code-reload/backends.md)脚本虚拟机 (VM) 实现了**托管内存**系统，该系统有时也称为脚本内存系统。这些 VM 提供了分为以下不同类型的受控内存环境：

* **托管堆**：VM 使用[垃圾收集器](/engine/6000.0/manual/analysis/performance-memory-overview/managed-memory/garbage-collector.md) (GC) 自动控制的一段内存。因此，托管堆上分配的内存称为 **GC 分配**。[性能分析器 (Profiler)](/engine/6000.0/manual/analysis/profiler.md) 将出现的所有此类分配记录为 **GC.Alloc** 样本。
* \*\*脚本堆栈：\*\*在应用程序进入和退出任何代码作用域时，会建立和解除此属性。
* \*\*本机 VM 内存：\*\*包含与 Unity 脚本层相关的内存。大多数情况下，您不需要操作本机 VM 内存，但最好了解它包含与代码生成的可执行代码相关的内存，尤其是在[泛型](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics)的使用、[反射](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection)使用的类型元数据以及运行 VM 所需的内存等方面。

由于托管内存系统使用 VM，所以它有一个受控环境，可自动跟踪分配的引用以管理分配的生命周期。这意味着在其他代码正在尝试访问内存时，应用程序不太可能过早释放内存。这也意味着可以在一定程度上防止在代码无法访问内存或未使用的内存堆积时发生的[内存泄漏](https://en.wikipedia.org/wiki/Memory_leak)。

在 Unity 中使用托管内存是管理应用程序中内存的最简单方法；但它也有一些缺点。垃圾收集器使用起来很方便，但它在释放和分配内存的方式上也难以预测，这可能会导致性能问题，例如垃圾收集器不得不停止以释放和分配内存时出现的卡顿。要解决这种不可预测性，可以使用 [C# 非托管内存层](#unmanaged-memory)。

有关托管内存工作方式的更多信息，请参阅有关[托管内存](/engine/6000.0/manual/analysis/performance-memory-overview/managed-memory.md)的部分。

## C# 非托管内存

**C# 非托管内存层**有助于访问本机内存层以微调内存分配，同时方便编写 C# 代码。

可以使用 Unity Core API 中的 `Unity.Collections `命名空间（包括 [NativeArray](/engine/6000.0/script-reference/unity-collections/native-array-1.md)）以及 [Unity Collections 包](https://docs.unity3d.com/Packages/com.unity.collections@latest)中的数据结构来访问 C# 非托管内存。如果使用 Unity 的 C# 作业系统或 Burst，则必须使用 C# 非托管内存。如需了解更多相关信息，请参阅有关[作业系统](/engine/6000.0/manual/scripting/optimization/job-system.md)和 [Burst](http://docs.unity3d.com/Packages/com.unity.burst@latest) 的文档。

## 本机内存

Unity 引擎的内部 C/C++ 核心有自己的内存管理系统，称为**本机内存**。在大多数情况下，无法直接访问或修改此内存类型。

Unity 将场景存储在项目、资源、图形 API、图形驱动程序、子系统和插件缓冲区中，并将分配存储在本机内存中，这意味着可以通过 Unity 的 C# API 间接访问本机内存。这意味着可以安全轻松地操控应用程序的数据，而不会丧失 Unity 本机核心上的原生代码和高性能代码的优势。

在大多数情况下，不需要与 Unity 的本机内存交互，但无论何时使用[性能分析器](/engine/6000.0/manual/analysis/profiler/window.md)，都可以通过[性能分析器标记](/engine/6000.0/manual/analysis/profiler/markers.md)看到它对应用程序性能的影响。还可以通过更改 Unity 本机内存分配器的一些可配置设置来调整应用程序的性能。有关更多信息，请参阅有关[本机内存](/engine/6000.0/manual/analysis/performance-memory-overview/native-allocators.md)的部分。
