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加载的资源都已经卸载, 否则会导致资源丢失(但内存中仍有实例)或重复加载
相关推荐
WarPigs11 小时前
Unity阴影
unity·游戏引擎
一只一只12 小时前
Unity之Invoke
unity·游戏引擎·invoke
tealcwu15 小时前
【Unity踩坑】Simulate Touch Input From Mouse or Pen 导致检测不到鼠标点击和滚轮
unity·计算机外设·游戏引擎
ThreePointsHeat15 小时前
Unity WebGL打包后启动方法,部署本地服务器
unity·游戏引擎·webgl
迪普阳光开朗很健康15 小时前
UnityScrcpy 可以让你在unity面板里玩手机的插件
unity·游戏引擎
陈言必行1 天前
Unity 之 设备性能分级与游戏画质设置与设备自动适配指南
游戏·unity·游戏引擎
CreasyChan2 天前
Unity DOTS技术栈详解
unity·c#·游戏引擎
CreasyChan2 天前
Unity的ECS(Entity Component System)架构详解
unity·架构·游戏引擎
神码编程2 天前
【Unity】 HTFramework框架(六十九)Log在编辑器日志中自定义点击事件
unity·编辑器·游戏引擎