Version: 6000.3
语言: 中文
Unity 中的内存
托管内存

Unity 中的内存简介

为了确保您的应用程序在运行时没有性能问题,了解 Unity 如何使用和分配内存非常重要。

Unity 使用以下内存管理层来处理应用程序中的内存:

  • 托管内存:使用托管堆和垃圾回收器自动分配和分配内存的受控内存层。
  • C# 非托管内存:可与Unity.Collections命名空间、Collections 包UnsafeUtility.MallocUnsafeUtility.Free.此内存类型称为非托管内存类型,因为它不使用垃圾回收器来跟踪和管理内存停止使用的时间,而是要求代码通过调用Dispose在集合上或Free在分配的内存上UnsafeUtility.Malloc.
  • 原生内存:Unity 用于运行引擎的 C++ 内存。它包含与项目中资产使用的内存等区域相关的内存,以及 Unity 不同原生子系统(如渲染或动画系统)的管理器。在大多数情况下,无法通过 C# 代码访问此内存,但由于它通常是应用程序内存占用的最大部分,因此如果要优化应用程序的内存使用,了解它非常有用。

托管内存

Mono 和 IL2CPP 的脚本虚拟机 (VM) 实现托管内存系统,有时称为脚本内存系统。VM 提供受控内存环境,分为以下不同类型:

  • 托管堆:VM 使用垃圾回收器自动控制的内存部分。
  • 脚本堆栈:这是在应用程序进入和退出任何代码范围时构建和展开的。
  • 本机虚拟机内存:包含与 Unity 脚本层相关的内存。

在 Unity 中使用托管内存是管理应用程序中内存的最简单方法,但它有一些缺点。垃圾回收器使用起来很方便,但它在释放和分配内存的方式上也不可预测,这可能会导致性能问题,例如卡顿,当垃圾回收器必须停止释放和分配内存时就会发生这种情况。若要解决这种不可预测性,可以使用 C# 非托管内存层

有关托管内存工作原理的详细信息,请参阅托管内存部分。

C# 非托管内存

C# 非托管内存层允许访问本机内存层以微调内存分配,并方便地编写 C# 代码。

您可以使用Unity.Collections命名空间(包括NativeArray)、Unity Collections 包中的数据结构,以及 Unity 核心 API 中的数据结构UnsafeUtility.MallocUnsafeUtility.Free以访问 C# 非托管内存。

如果使用 Unity 的作业系统Burst,则必须使用 C# 非托管内存。此外,为了能够使用 Burst,您只能使用Unity.Collections命名空间或满足 C# 非托管约束的类型。

Unity 的本机代码(有时是本机分配器)分配 C# 可通过这些 API 访问的内存。因此,内存探查器等工具将 C/# 非托管内存与本机内存分组。

原生内存

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

Unity 将场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表
在您的项目中,资产、图形 API、图形驱动程序、子系统、插件在 Unity 外部创建的一组代码,用于在 Unity 中创建功能。可以在 Unity 中使用两种插件:托管插件(使用 Visual Studio 等工具创建的托管 .NET 程序集)和本机插件(特定于平台的本机代码库)。更多信息
请参阅术语表
缓冲区,以及本机内存中的分配。这意味着您可以通过 Unity 的 C# API 间接访问本机内存,并以安全的方式作应用程序的数据,并从内部 C/C++ 核心中的本机高效代码中获益。

大多数时候,您不需要与 Unity 的本机内存交互,但您可以在使用分析器帮助您优化游戏的窗口。它显示了在游戏的各个领域花费了多少时间。例如,它可以报告渲染、动画制作或游戏逻辑所花费的时间百分比。更多信息
请参阅术语表
通过探查器标记放置在代码中,用于描述 CPU 或 GPU 事件,然后显示在 Unity 探查器窗口中。默认添加到 Unity 代码中,或者您可以使用 ProfilerMarker API 添加自己的自定义标记。更多信息
请参阅术语表
.您还可以通过更改资产的设置以及通过 Unity 本机内存分配器的可配置设置来调整应用程序的性能。有关详细信息,请参阅本机内存分配器

其他资源

Unity 中的内存
托管内存