当我们在预制体上做了修改后,如果想要把修改应用到asset中存储的prefab中,就需要进行应用:
而如果同时需要应用的prefab太多的话,比方说有几十上百个,这种一个一个应用的方法就会很累人,我们可以写一个脚本来帮助我们做这件事,话不多说,先放代码:
[MenuItem("TimelineTools/应用选中预制体")]
??? private static void ApplySelectedPrefabs()
??? {
??????? GameObject[] selectedGameobjects = Selection.gameObjects;
??????? for(int i = 0; i < selectedGameobjects.Length; i++)
??????? {
??????????? GameObject obj = selectedGameobjects[i];
??????????? //如果场景中的预制体实体和asset中的预制体连接
??????????? if(PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.Connected)
??????????? {
??????????????? //找到asset中对应存储的预制体
??????????????? Object parentObject = PrefabUtility.GetCorrespondingObjectFromSource(obj);
??????????????? string path = AssetDatabase.GetAssetPath(parentObject);
??????????????? //将预制体实例应用到asset中存储的预制体上
??????????????? PrefabUtility.SaveAsPrefabAssetAndConnect(obj, path, InteractionMode.UserAction);
??????????????? AssetDatabase.Refresh();
??????????? }
??????? }
}
这个脚本需要引用unityEditor,其中Selection.gameObjects即为我们当前选中的对象列表。
PrefabUtility.GetPrefabInstanceStatus这个函数用来判别一个物体的预制体状态,
用PrefabInstanceStatus枚举表示物体的状态,有已连接、未连接、丢失资源、不是预制体这几个状态选项,可以在unity PrefabUtility官方API上查询。
PrefabUtility.GetCorrespondingObjectFromSource的作用是找到预制体实例的资源位置,以便于后续更改。而PrefabUtility.SaveAsPrefabAssetAndConnect这个函数,根据官方上的解释,则是由给定路径创建一个预制体资源,以当前游戏对象的内容作为实例,也就是替换原来的预制体资源。
见API上的解释:
?
除了靠同时选中来执行操作外,我们还可以根据标签来进行预制体的应用,代码如下:
[MenuItem("TimelineTools/应用所有标记预制体")]
??? private static void ApplyMentionedPrefabs()
??? {
??????? List<GameObject> mentionedPrefabs = FindObjects("prefab");
??????? foreach(GameObject obj in mentionedPrefabs)
??????? {
??????????? //如果场景中的预制体实体和asset中的预制体连接
??????????? if (PrefabUtility.GetPrefabInstanceStatus(obj) == PrefabInstanceStatus.Connected)
??????????? {
??????????????? //找到asset中对应存储的预制体
??????????????? Object parentObject = PrefabUtility.GetCorrespondingObjectFromSource(obj);
??????????????? string path = AssetDatabase.GetAssetPath(parentObject);
??????????????? //将预制体实例应用到asset中存储的预制体上
??????????????? PrefabUtility.SaveAsPrefabAssetAndConnect(obj, path, InteractionMode.UserAction);
??????????????? AssetDatabase.Refresh();
??????????? }
??????? }
??? }
??? //根据tag在hierarchy里找到物体,包括隐藏的物体
??? private static List<GameObject> FindObjects(string tag)
??? {
??????? List<GameObject> gameObjects = new List<GameObject>();
??????? foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)))
??????? {
??????????? if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
??????????? {
??????????????? if (go.tag == tag)
??????? ????????????gameObjects.Add(go);
??????????? }
??????? }
??????? return gameObjects;
}
和上一个方法的区别就是添加了一个寻找方法,寻找到对应标签的游戏对象组,关于这个寻找的方法,可以参照我的另一篇博客:https://blog.csdn.net/weixin_43347688/article/details/107322746