Unity 内存管理的专业提示
优化是游戏开发中很重要的一部分,涉及的方面主要有 CPU,GPU,内存,网络等。 在这篇博客中,主要会写关于内存相关的优化,Unity 是如何管理内存的,以及怎样才能使游戏更高效地运行。 在深入到 Unity 之前,我们先来看一下内存是如何工作的。 操作系统会在物理内存的基础上,创建一个虚拟内存,用于程序运行。在这个抽象中,会有一些虚拟地址空间(VAS) 在内存优化上,主要考虑两部分,也就是栈(Stack)和堆(Heap)。在理解栈和堆之前,首先要理解在 Unity 中,数据的类型,可分为值类型,和引用类型。对于值类型的数值,会直接存储在栈上,并且是可以直接复制的。例如,int, float, bool, struct, Color Vector3 等。 而引用类型的数据,则是存储在堆上,但是,指向这个数据的指针,是存储在栈上的。 栈(Stack) 存储值类型 存储引用类型的指针 由 CPU 自动管理,无须程序员关心。在函数调用时,参数将自动申请内存放入栈中,当函数结束时,这些参数又会从栈取出,释放内存,这一切操作都是自动的。 栈比堆的速度快 栈的容量有限,如果超过上限,则会出现栈溢出。 栈的运行方式是 Last in first out。也就是后进先出,或者说先进后出。 堆(Heap) 可以存储引用类型和值类型的数据 由程序员手动管理 内存空间不一定是连续的 比栈速度慢 可以扩展空间大小 接下来,我们来理解什么是 “垃圾”,以及什么是 “垃圾回收”。 垃圾 存储在栈上的一个指向堆数据的指针结束时(释放时),堆上的数据没有用了,对于这样的对象,可以理解为 “垃圾”。 垃圾回收 为了解决垃圾内存的问题,.Net 有对应的垃圾回收系统。 在初始化一个新的进程时,语言运行时会为该进程保留一个连续的地址空间区域。这个保留的地址空间称为托管堆。托管堆维持指向堆中下一个对象的地址指针。 从托管堆中分配内存,比非托管堆中分配内存要快。 垃圾回收系统会创建一个包含从根可访问的所有对相的图。当一个对象不在这个图中,也就是无法从根节点访问时,垃圾回收系统会将这部分内存视为垃圾,并在合适的时机释放为其分配的内存。 Unity 的内存管理系统 Unity 的内存管理分为三部分。 托管内存 托管内存使用托管堆以及垃圾回收系统自动分配和释放内存,而提供这个功能的是 Mono 或 IL2CPP。在 Unity 中我们大部分时候使用的都是托管内存,所以 New 对象时,都不考虑释放,垃圾回收系统会帮我们处理掉。 C# 非托管内存 C#非托管内存层使你可以在编写C#代码的方便下访问本机内存层以微调存储器分配。 您可以在Unity Core API中使用Unity.CollectionsNamespace(包括NativeArray),以及Unity Collections软件包中的数据结构来访问C#非托管的内存。如果您使用Unity的 Job System 或 Brust,则必须使用C#非托管内存。...