原文
原文在这里
问题
最近,我在用unity编辑器脚本做一些实验,但对LoadAssetAtPath、LoadAllAssetAtPath、LoadMainAssetAtPath这三个玩意感到困惑,搞不清楚其中区别与联系。
我有这样的一个预制,它的路径是~/Assets/Resources/Prefabs/something.prefab。我是这样理解的:
- LoadAssetAtPath,只加载指定路径的一个资产,我会得到一个prefab object
- LoadAllAssetAtPath,加载指定路径的所有资产,我会得到这个prefab object和它的所有孩子object
- LoadMainAssetAtPath,加载指定路径的“主”资产,懵逼了什么叫主?实验得的结果和LoadAssetAtPath一样,这个其实和LoadAssetAtPath有什么区别?
另外 ,我使用LoadAllAssetAtPath,加载得到的资产,好似会有重复?我的预制结构是这样的:
something.prefab
|_Tab1
|_child 1
|_child 2
把得到的资产的名输出来,是这样子的
我希望有大佬能教一下我,这几个接口的区别,以及AssetDatabase的特点的相关知识。先过谢谢啦。
回答
首先要明白什么是“asset”资产是什么玩意。总体来说,所有从UnityEngine.Object派生出来的类,都叫资产,因为只有这些类,才可以被Unity序列化(资产,唯一可以被Unity序列化的)。对prebab文件使用LoadAllAssetAtPath,没什么实际意义,因为这样做的话,会把prebab中的每一个单个的object加载出来。记住,GameObject和Transform这些,都是可序列化的类,而且他们有一样的名字(这就解释了,为什么你的等到了重复名字的object的问题了)。
LoadAllAssetAtPath用在包含多个资产的单个文件的话,才是有实际意义的。比如,用在 ".asset"文件。一个资产文件,可以包含一个可序列化的游戏对象,一个材质,多个纹理,或者其它的资产(如ScriptableObjects,ScriptableObjects?可脚本化对象?什么玩意?)
为了更好地理解,可以把 “asset serialization mode” 设置成"Force Text",即资产序列化模式设置为文本。这样,你就在文件编辑器中,打开.prefab、.scene 、.asset等文件啦。这些文件会以序列化文本的形式组织,用的是YAML格式。
下面对比一下那三个方法:
- LoadAllAssetAtPath 就像前面提到的,简单地加载指定路径文件中的所有序列化的对象。
- LoadMainAssetAtPath 加载指定路径文件中“主要”资产(只有一个就无所谓主要了,这里的主要是指多个的情况下,主要的那个。比如,对prebab而言,主要的是整个根game object)。什么叫主要?Unity的内建类型,会有更高的优先级(更主要),这个优先级是相对你自己的ScriptableObject 类而已的。意思是,如果你有一个你的ScriptableObject,把它保存为.asset文件,(选中.asset之后)你会在inspector窗口中看到这个ScriptableObject。然后,如果你把材质加到同一个.asset文件,这个材质就会成为.asset文件的“主要”资产。如果.asset文件中没有特殊优先级的文件,就会返回文件中的第一个资产。
- LoadAssetAtPath 加载定路径文件中的单个资产。这个方法基本和LoadMainAssetAtPath差不多。但这个方法,是加载指定类型的。它只会返回你指定的类型(以及对应的派生类型)的资产。举例,如果你指定Texture,会得到各种Texture,如Texture2D, RenderTexture, Texture3D。指定Component,会得资产中的第一个Component(很可能是Transform component)。
现在应该对这个事更清晰吧,GameObject实质上没有层级结构的。GameObject只是一个组件的容器。GameObject之间的层级结构是由Transform组件维系的。
你可以把一个个GameObject想象成在文件柜中的一个个抽屉,把Component想象成抽屉里的一份份文件。抽屉是没有层级关系的,只是平级地排在那里。但是,抽屉里可以有一份叫Transform 的文件,你可以往这个文件里写,这个Transform 文件的父亲叫”5号抽屉中的Transform 文件“,文件里还可以写有这个文件的孩子Transform 文件是哪些。
注意,这里的Transform 组件表示层级关系时,不是通过持有GameObject的引用的,它持有的是Transform 组件的引用。而且,每一个Transform 组件都有一个GameObject的引用,表示它所属的容器(GameObject是个组件容器)。