Assets和Objects
Assets是存储在硬盘上的文件,保存在Unity项目的Assets文件夹下,比如贴图,材质,模型,音频都是Assets。一些Assets中含有Unity的原生数据,例如材质,其他Asset则需要转换成原生格式例如FBX文件
Objects适用于描述某个资源的特定实例的序列化数据集合 可以是Unity使用的任意类型的资源 mesh script audiocilp
Assets和Objects之间存在一对多的关系,也就是说,Asset文件内能包含一个
所有的UnityObject.Objects都可以引用其他的UnityEngine.Objects被引用的物体可以和引用物体位于同一个Asset文件内,也可以是由其他Asset文件导入的 例如材质文件通常有一个或多个纹理对象的引用 纹理通常来自纹理资源文件导入的
序列化时候这些文件有两部分数组组成文件GUID和LocalID 文件GUID存储了资源的Asset文件 LocalID是局部唯一的 在每个Asset文件中LocalID是唯一的标记Asset文件中的每个Object
打开材质本身可以看见LocalID mate可以看见guid
GUID提供文件路径的抽象表示,只是使用GUID关联具体的文件 由于一个Asset文件可以包含多个Object文件因此需要用LocalID明确标记每个不同的Object如果一个文件Asset文件关联的GUID丢失 name所有对该文件的Objects的引用将丢失 mate文件丢失,unity会重新生成
unity维护了一个具体文件路径与GUID的映射关系 当一个Assset被加载或导入,就会新增一个映射项,该映射项将文件路径与文件的GUID对应起来 如果meta文件丢失但其文件路径没变,unity保证生成的GUID不变 如果Asset文件路径变化meat文件没有一起移动,那么所有对该Asset引用会丢失
资源导入
非unity原生资源必须导入进unity才能使用,通过asset importer实现的在资源导入时自动调用 导入的结果是一个或多个Objects在unity中你可以看到一个父对象包含多个子对象 公用一个GUID ,内部文件通过LocalID区分
实例ID
尽管GUID和LocalID健壮耐用,但是GUID的比较耗时,因此Unity在内部维护一份缓存,这份缓存将GUID和LocalID独一无二的整数,这些整数被称为InstanceID,每当有新的Objects加入到缓存中,InstanceID以简单的单吊递增的方式进行复制,缓存维护了Instanceid guid localid (后两个在磁盘上)以及Object在内存中的实例(如果object已经加载到内存中)之间的映射 维护相互之间的引用关系,通过Instanceid快速找到对应的加载的object,如果object没有加载那么可以通过GUID和LocalID来找到Object源数据,然后加载相应的object
程序启动时,项目内置对象(比如场景中使用的对象)的数据 以及在Resources文件夹中的对象的数据将被初始化到InstanceID缓存中,当运行时有新的资源加载时 以及在Assetbundle中加载对象时,就会在缓存中添加Instanceid项,Instanceid只有被认为已经过时的情况下才会从缓存中删除 这种情况发生在一个AssetBundle被卸载时,除了对导致对应的Instanceid认为过时,GUID,LocalID之间的映射数据也会被从内存中删除,如果AssetBundle重新加载的话 那么从该AssetBundle加载每一个对象都会创建一个新的Instanceid
所有程序集在应用程序第一次启动时会被全部加载进来 可以使得不同的monobehaver可以引用共同的具体类
资源的生命周期 有两种加载Onject的方式:自动加载和显示的手动加载 当一个InstanceID被解引用其对应的Object当前没有加载到内存中,并且object的源数据能被定位到Object会自动加载 Object还能够在脚本中手动加载,AssetBundle.loadasset方式加载Object,如果一个文件GUID和LocalID都没有对应的InsanceID,或者InstanceID对应的Object没有被加载并且对应的GUID和LocalID是无效的Object就不会加载,但引用关系会保留出现missing
Object会在下列时刻被自动加载:
- 映射到该Object的Instance ID被反向引用(Dereference)
- Object当前没有被加载到内存中
- Object的源数据可以被定位
显式地加载Object。当Object被加载后,Unity会通过把每个引用的File GUID和Local ID转换到Instance ID来查找引用目标。如果满足了下面的两个条件,在Object的Instance ID首次被反向引用时它会被请求式(On-demand)的加载:
- Instance ID引用了一个当前没有被加载的Object
- Instance ID在缓存中含有合法的File GUID和Local ID
Object卸载的情况
1清理未被引用的asset是 未被引用的Object会被自动卸载 当场景切换或Resources.unloadunusedassets会触发,这一过程仅卸载那些没有被引用的Object —— 一个Object只会在没有任何Mono变量或其他的活动Object持有对它的引用的时候才能被卸载。另外,所有被标记为HideFlags.DontUnloadUnusedAsset和HideFlags.HideAndDontSave的对象都不会被卸载。
2来自Resources文件夹的Object在调用resource.unladasset函数时销毁但Instanceid会被保留,并且含有有效的FileID和LocalID条目,如果在Object销毁后有任何对对象的引用时,unity会重新通过instanceID找到GUID和LocalID 然后加载进来
3来自AssetBundle的Object在调用AssetBundle.unload(true)函数时会被立即销毁同时也会使得instanceid的guid localid变得无效 任何对该对象引用也会变成missing,如果调用AssetBundle.unload(false)从AssetBundle加载的Object不会销毁,但是unity会使用它们的Instanceid所引用的GUID和LocalID变成无效 系统仍有这些OObject的引用,unity没办法在加载这些object