欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

unity 一键应用多个预制体

程序员文章站 2022-04-12 09:13:26
当我们在预制体上做了修改后,如果想要把修改应用到asset中存储的prefab中,就需要进行应用:而如果同时需要应用的prefab太多的话,比方说有几十上百个,这种一个一个应用的方法就会很累人,我们可以写一个脚本来帮助我们做这件事,话不多说,先放代码:[MenuItem("TimelineTools/应用选中预制体")] private static void ApplySelectedPrefabs() { GameObject[] selectedGa......

当我们在预制体上做了修改后,如果想要把修改应用到asset中存储的prefab中,就需要进行应用:

unity 一键应用多个预制体

而如果同时需要应用的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上的解释:

unity 一键应用多个预制体

 

除了靠同时选中来执行操作外,我们还可以根据标签来进行预制体的应用,代码如下:

[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