1.1 Unity资源生命周期管理与内存机制

1.资源生命周期管理

2.资源标识与引用方式

3.资源卸载与内存释放机制


1.资源生命周期管理

csharp 复制代码
资源生命周期分为: 编辑时 -> 构建时 -> 运行时

1).编辑时(Edit - time)

当我们将原始资源拖入到Assetsw文件夹时, unity会通过导入设置(Import Settings)将原

始文件转换为unity内部可用的格式(如纹理会被转换为Texture2D)

a.导入设置(Import Settings)决定了资源如何被转换和优化

b.资源之间的引用通过GUID(全局唯一标识符)和Local ID进行管理, 每个资源文件都有一个

GUID, 而文件中的每个子资源(如一个FBX文件中的多个Mesh)有一个Local ID

c.编辑时的引用关系被记录在.meta文件中
csharp 复制代码
2).构建时(Build - time)

当我们构建项目时, Unity会收集所有被场景或资源引用的资源, 并根据构建设置进行处理

a.依赖关系分析: Unity会分析资源之间的引用关系, 确保被引用的资源被打包

b.资源打包: 资源可以被打包到AssetBundle
csharp 复制代码
3).运行时(Run - time)

在游戏运行过程中, 资源需要被加载到内存中才能被使用; Unity提供了多种资源加载方式,  

如Resources.Load, AssetBundle.LoadAsset等

a.加载时机: 可以在启动时加载, 也可以在需要时动态加载

b.内存管理: 加载的资源会占用内存, 需要在不使用时及时卸载, 避免内存泄露

c.异步加载: 为了不阻塞主线程, 可以使用异步加载方式

2.资源标识与引用方式

csharp 复制代码
1).资源标识

Unity使用两种方式来标识资源

a.GUID: 每个资源文件在创建时都会分配一个唯一的GUID, 存储在.meta中; 用于在项目内唯

一标识资源

b.Local ID: 一个资源文件(如FBX)可能包含多个子资源(如多个Mesh), 每个子资源通过

Local ID来标识

注: "构建时, Unity会将GUID和Local ID映射到运行时ID, 以便在运行时加载"
csharp 复制代码
2).引用方式

a.直接引用

在Inspector面板中将一个资源拖拽到组件的一个字段上, 这种引用在编辑时建立, 运行时直接

可用

b.Resources文件夹下的资源

使用Resources.Load方法, 通过路径字符串加载

c.AssetBundle

将资源打包成AssetBundle, 然后通过AssetBundle.LoadAsset加载; 这种方式支持动态更

新和按需加载

d.间接引用

通过ScriptableObject或配置文件存储资源路径或地址, 然后在运行时根据这些信息加载资源

3.资源卸载与内存释放机制

csharp 复制代码
1).资源卸载的重要性

如果不卸载不再使用的资源, 它们会一直占有内存, 导致内存占用不断增加, 最终可能引起内存

不足, 导致游戏崩溃
csharp 复制代码
2).资源卸载

a.Resources文件夹下的资源卸载

- Resources.UnloadAsset(obj): 卸载通过Resources.Load加载的指定资源, 但只能卸

载没有引用的资源(即没有被任何场景中的对象引用的资源)

- Resources.UnloadUnusedAssets: 会卸载所有不再被引用的资源, 这些资源包括通过

Resources.Load加载的资源, 也包括场景中的资源, 但注意: 它不会卸载AssetBundle文件

本身, 但会卸载从AssetBundle中加载出来的、且当前没有引用的资源

b.AssetBundle的资源卸载

- AssetBundle.Unload(false): 卸载AssetBundle文件的内存镜像, 但是不会销毁已经

从该AssetBundle中加载的资源

- AssetBundle.Unload(true): 卸载AssetBundle文件的内存镜像, 并且销毁所有已经从

该AssetBundle中加载的资源; 注意: "如果这些资源还被其他地方引用, 则可能会丢失"

记住这个原则: AssetBundle像是资源的"容器",Resources.UnloadUnusedAssets只清

理"内容物",不清理"容器"本身
csharp 复制代码
3).内存释放的触发条件

a.调用Resources.UnloadUnusedAssets会触发本地堆中资源的释放, 同时也会触发托管堆

的GC

b.垃圾回收(GC)会释放托管堆中不再使用的对象

c.卸载AssetBundle(Unload(true))会立即释放该AssetBundle加载的资源占用的本地堆内

存
csharp 复制代码
4).常见问题

a.资源引用残留: 即使场景中没有对象使用资源, 如果资源被静态变量或全局变量引用, 也会被

视为正在使用, 无法卸载

b.AssetBundle卸载时机: 如果使用AssetBundle.Unload(false), 需要确保所有从该

AssetBundle加载的资源都已经卸载, 否则会导致资源丢失(但内存中仍有实例)或重复加载
相关推荐
小李也疯狂2 小时前
Unity 中的立方体贴图(Cubemaps)
unity·游戏引擎·贴图·cubemap
牛掰是怎么形成的2 小时前
Unity材质贴图引用陷阱:包体暴涨真相
unity·材质·贴图
呆呆敲代码的小Y2 小时前
【Unity工具篇】| 超实用工具LuBan,快速上手使用
游戏·unity·游戏引擎·unity插件·luban·免费游戏·游戏配置表
EQ-雪梨蛋花汤2 小时前
【Unity优化】Unity多场景加载优化与资源释放完整指南:解决Additive加载卡顿、预热、卸载与内存释放问题
unity·游戏引擎
我的offer在哪里3 小时前
用 Unity 从 0 做一个「可以玩的」游戏,需要哪些步骤和流程
游戏·unity·游戏引擎
泡泡茶壶ᐇ3 小时前
Unity游戏开发入门指南:从零开始理解游戏引擎核心概念
unity·游戏引擎
YigAin5 小时前
Unity中的Lock,到底在锁什么,什么时候该用?
unity
Var_al5 小时前
抖小Unity WebGL分包命令行工具实践指南
unity·游戏引擎·webgl
天人合一peng7 小时前
unity 通过代码修改button及其名字字体的属性
unity·游戏引擎
GLDbalala11 小时前
Unity基于自定义管线实现经典经验光照模型
unity·游戏引擎