当我们在预制体上做了修改后,如果想要把修改应用到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

本文地址:https://blog.csdn.net/weixin_43347688/article/details/107322813