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加载的资源都已经卸载, 否则会导致资源丢失(但内存中仍有实例)或重复加载
相关推荐
Sator17 小时前
Unity烘焙光打包后光照丢失问题
unity·光照贴图
GLDbalala14 小时前
Unity 实现一个简单的构建机
unity·游戏引擎
JIes__1 天前
Unity(二)——Resources资源动态加载
unity·游戏引擎
地狱为王1 天前
Unity使用NovaSR将沉闷的16kHz音频升频成清晰的48kHz音频
unity·游戏引擎·音视频·novasr
dzj20211 天前
Unity中使用LLMUnity遇到的问题(二)——LLMUnity脚本学习和探索
unity·llmunity
警醒与鞭策2 天前
Cursor Agent Skill 原理及LLM , Agent, MCP ,Skill区别
android·unity·ai·cursor
tealcwu2 天前
【Unity资源】Unity MCP 介绍
unity·游戏引擎
Thomas_YXQ2 天前
Unity3D中提升AssetBundle加载速度的详细指南
java·spring boot·spring·unity·性能优化·游戏引擎·游戏开发
Miss_SQ3 天前
Unity接入AI—Deepseek,数据流式传输
unity·ai