Unity内存优化

本文详细介绍了Unity游戏开发中的内存优化策略,包括资源管理、纹理压缩、使用图集(Atlas)、AssetBundle打包与加载、GC管理、对象池、代码优化和内存泄漏检测,以及Unity的DOTS架构和相关技术如ECS、Burst编译器和Jobs系统。
摘要由CSDN通过智能技术生成

导语

在Unity中进行内存优化是确保游戏性能良好的关键部分之一。优化内存可以减少应用的内存占用,降低加载时间,提高稳定性。

内存优化技巧

资源管理

纹理压缩

在 “Texture Import Settings” 部分,有一个名为 “Texture Compression”(纹理压缩)的下拉菜单,你可以在这里选择适合你的平台的压缩格式。Unity支持的常见压缩格式包括:

  • Automatic(自动):Unity将自动选择最佳的压缩格式,通常是ASTC(Android)或BC7(iOS,PC)。
  • ASTC(Android):适用于Android设备的高效压缩格式。
  • PVRTC(iOS):适用于iOS设备的高效压缩格式。
  • ETC2(Android):另一种适用于Android的压缩格式。
  • BC7(PC,iOS):适用于PC和iOS设备的高质量压缩格式。

使用图集(Atlas)

以Unity2021为例,需要打开 “Window” > “Package Manager”,找到并安装2D Sprite

随后在 “Assets” 菜单中,选择 “Create” > “Sprite Atlas”(Unity2022中是"Create" > “2D” > “Sprite Atlas”)。这将在项目视图中创建一个新的Sprite Atlas对象。
以下介绍一些常用的Atlas设置说明:

  • “Padding”:精灵之间的间隔。
  • “Generate Mip Maps”:是否为图集生成Mip Maps。个人理解为缩放技术,使用缩放值时可以减少锯齿的发生。精灵不需要缩放时,则不需要勾选。
  • “Tight Packing”:是否将精灵紧密打包,以减少空白区域。
  • “Allow Rotation”:是否允许旋转精灵以更好地填充空间。

使用AssetBundle

将资源打包为AssetBundle,以便在需要时加载。这对于资源较多的游戏非常有用。

打包AssetBundle

选中资源时,Inspector面板中的最下方会显示当前的AssetBundle路径,在其中填入AssetBundle的完整路径即可标记为需要打包的AssetBundle。
该操作也可在代码中实现:

var obj = AssetImporter.GetAtPath(filename);
obj.assetBundleName = string.Format("{0}/{1}.unity3d", Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename));

标记后,调用以下代码即可打包AssetBundle:

var BuildFolderPath = string.Format("../Bundles/{0}/", BuildTarget.StandaloneWindows.ToString());
if (!Directory.Exists(BuildFolderPath)) Directory.CreateDirectory(BuildFolderPath);
BuildPipeline.BuildAssetBundles(BuildFolderPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
加载AssetBundle

加载AssetBundle的方式如下:

// 指定AssetBundle的名称
string assetBundleName = "myassets";

// 加载AssetBundle
AssetBundle assetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, assetBundleName));

// 加载AssetBundle中的资源
GameObject prefab = assetBundle.LoadAsset<GameObject>("myPrefab");

管理AssetBundle

如果一个AssetBundle依赖于其他AssetBundles,你需要管理这些依赖关系。确保在加载AssetBundle之前,已加载其所有依赖的AssetBundles。常见的方法有对AssetBundle及依赖项进行引用计数,对无引用的AssetBundle进行释放。

资源的预加载

当游戏过程中,需要用到大量资源时,可以加入一个加载界面,用于进行资源的预加载。

资源的卸载

在不再需要的资源上调用 Destroy 或 UnloadAsset,特别是对于不再使用的游戏对象、材质、纹理和声音资源。

GC的管理

游戏运行的过程中产生的GC是内存优化的大敌,它由引用对象的释放产生,因此为优化GC产生的性能损耗,是内存优化的必须步骤之一。

对象池

由于在游戏中,我们经常需要频繁的创建和销毁一些对象,包括数据对象和GameObject对象,他们都属于引用类型。为了减少他们产生的GC,我们可以使用对象池的方式去管理他们,而不是重复创建。

优化代码

由于GC是由引用对象的释放产生的,在代码逻辑上,可以尽可能的减少引用类型的使用,改用结构体代替。
若是项目由Lua编写,则尽可能的减少引用类型的使用,尽可能的用一些简单的值类型来代替运算。
减少引用对象的互相引用,确保无需使用的对象可以正常释放。
当单个节点重复产生GC时,可以考虑使用对象池。
字符串也为引用对象,为避免重复创建回收,可以考虑建立一个常用的字符串常量数据类。

检查内存泄漏

使用Unity的Profiler工具来检查内存泄漏。确保游戏中的对象被适当地释放,不会长时间占用内存。
可以通过Profiler提供的接口来判定一段代码中的占用内存及耗时情况,但需注意BeginSample和EndSample不能跨帧,即两个方法需要在同一帧执行。

Profiler.BeginSample("TempName");
// do something
Profiler.EndSample();

DOTS

Unity DOTS(Data-Oriented Technology Stack)是Unity的一套技术栈,旨在提高游戏性能,特别是在大规模物理仿真、粒子系统和AI等方面。DOTS的核心理念是将重点放在数据与系统的处理上,以提高CPU和内存的利用率。

ECS(Entity-Component-System)架构

DOTS采用ECS架构,与传统的面向对象编程(OOP)方式有所不同。在ECS中,游戏对象被分解为实体(Entity)、组件(Component)和系统(System)。这种架构更有利于数据的并行处理,以及减少内存碎片化。

Burst编译器

DOTS引入了Burst编译器,它是一种高度优化的C#编译器,能够将C#代码编译成高效的本地代码,从而提高了游戏的运行速度。Burst编译器特别适用于数学和物理计算等计算密集型任务。

Jobs系统

DOTS的Jobs系统允许你以并行的方式执行任务,以充分利用多核CPU。这对于处理大量数据、物理模拟和AI计算等任务非常有用。

参考资料

参考资料:DOTS从原理到应用-雨松MOMO

总结

内存优化是一个迭代的过程,需要不断地监测和改进。使用Unity的Profiler和Memory Profiler等工具来帮助你监测内存使用情况,以找到潜在的问题并优化内存管理。

若有遗漏或描述错误、理解错误的地方,欢迎讨论指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值