unity 资源管理

时间:2024-03-30 16:05:13

文件的基本概念

Asset :保存在unity项目文件夹Assets 下面的磁盘文件
Object: 具体实列对象的序列化
Assets 由一个或者多个Object组成

定位资源

unity 使用GUID 和 fileID来定位文件。
GUID:定位文件的位置,定位一个Asset
fileID: 定位Asset 里面的一个Object (unity 描述为Local ID 实际上文件保存的是fileID)

GUID 保存在 .meta 文件里面,UnityEditor 负责维护GUID 和具体位置间的映射关系,在UnityEditor 打开的时候删除.meta文件会重新生成一个相同GUID 为.meta 文件不会造成引用的丢失,如果关闭了那么从新生成的GUID没有保证及引用关系科可能会丢失
使用这两个组合起来就可以定位到一个具体的Object,抽象出来与不需要关心具体的资源路径。有了GUID和LocalID 引用的对象可以随意移动保存位置,只要这两个没有变化,引用就不会丢失

图示

打开材质可以看到他的fileID
unity 资源管理
打开她的.meta 文件可以看到他的GUID
unity 资源管理
一个引用了改材质的场景打开该文件可以看到引用的GUID 和 fileID
unity 资源管理

一个New Material 材质引用了一个shader 和一张图片,下面是他们的.mete文件和 材质文件里面保存的数据
unity 资源管理

资源导入

unity在资源导入的时候会对导入资源做一个本地化的处理(让unity识别,比如FBX导入),和根据目标设置做一次处理,比如纹理的压缩,这个步骤是比较耗时的这些转换unity缓存起来不用每次启动都转换一次,保存在Library/metadata/ 文件夹下面的GUID 前面两位文件夹里面,文件的名称就是GUID 保存二进制的数据。这个过程是对所有资源,包括本地资源如shader等

运行时的资源定位

在运行是为了更高效Unity 引用了instanceID,instanceID 对GUID和fileId 有一个映射,InstanceID 是单调递增的,每加载一个资源就对应了一InstanceID,在运行的对象中引用的是instanceID 如果引用对象没有instanceID 但是GUID和fileID 能定位到资源就可以先加载资源然后给他们一个instanceID,在应用启动中instanceID 会立即初始化所有需要用到的资源,如场景的引用,Resources 文件夹下的Object(unity 官方建议不要使用Resources )
如果资源是从AssetBundles 中加载出来的,当资源卸载时当前instanceID将会移除,重新加载这个资源时会重新生成一个新的instanceID

代码资源

ScriptableObject unity 提供一个方便***数据的类型
MonoBehaviour 我们大部分写代码的地方,它有一个MonoScript 的引用,这个MonoScript是定位一个具体类的,MonoScript包含三个部分,使得定位一个具体的类(官方称为 script class)
1.程序集名称.
2.类名称
3.名称空间
在building 项目时unity把脚本编译到了Mono 程序集中 Plugins文件夹以外的打到了 Assembly-CSharp.dll 中,Plugins中的打到了Assembly-CSharp-firstpass.dll 中
这些dll 和其他资源不一样,他们都是在应用程序启动时全部加载了,这也是AssetBundles 中脚本可以引用不同AssetBundles 脚本的原因

资源加载

什么时候会自动加载资源
满足三个条件
1.instanceID被其他对象引用
2.资源没有被加载出来
3.资源能够被加载

资源加载时间花费阶段
1.读取资源(从存储、AssetBundle、其他GameObject)
2.设置transform的parent关系
3.实列化对象和对象上面的组件(Component)
4.调用对象和组件的Awake 方法

最后3步不管是Clone已经存在的对象还是从存储器里面加载需要花费的时间的是相同的,在设备上面从内存读取数据比从存储设备读取速度要快很多,不同平台的存储器读取速度也有大不同之处。所以对于加载一个大物体来说主要的时间花费的存储设备的IO 上面,一个大层级的对象比如包含100个对象都需要序列化,如果对象是重复的建议考虑加载一个出来后然后用代码复制,减少加载的IO时间。

资源卸载

资源卸载的3种情景
1.对象自动卸载,触发条件 a场景改变,不是以add模式 b调研了Resources.UnloadUnusedAssets 同时没有任何对象引用了改对象 如何对象设置了 HideFlags.DontUnloadUnusedAsset and HideFlags.HideAndDontSave 则不会卸载
2.对于Resources 文件夹下的资源可以使用 Resources.UnloadAsset 如何该资源被引用了则不会被卸载。同时该资源的instanceID 没有被卸载如果该资源被引用该资源会被重新加载出来
3.对于AssetBundles AssetBundle.Unload(true)会卸载该AssetBundles里面加出来的所有资源,及时被引用了,会造成引用丢失情况。AssetBundle.Unload(fase) 卸载没有被引用的资源同时该资源的instanceID 被移除当重新加载时会重新生成一个新的instanceID

参考资料

unity官方链接