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加载的资源都已经卸载, 否则会导致资源丢失(但内存中仍有实例)或重复加载