如果有使用搜索的对象,如何用包括孩子在内的预制件替换选定的对象?

本齐·阿夫鲁米(Benzi Avrumi)
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PrefabReplace : EditorWindow
{
    [SerializeField] private GameObject prefab;
    private bool selectionChanged;
    private string objectsToSearch = "";
    private List<GameObject> foundObjects = new List<GameObject>();
    private List<GameObject> duplicatedObjects = new List<GameObject>();
    private bool searched = false;
    private int count = 0;
    private int countChilds = 0;
    private bool countChildren = false;

    [MenuItem("Tools/Prefab Replace")]
    static void CreateReplaceWithPrefab()
    {
        int width = 340;
        int height = 300;

        int x = (Screen.currentResolution.width - width) / 2;
        int y = (Screen.currentResolution.height - height) / 2;

        GetWindow<PrefabReplace>().position = new Rect(x, y, width, height);
    }

    private void OnGUI()
    {
        Searching();
        GUILayout.Space(50);
        Replacing();
    }

    private void Searching()
    {
        GUI.Label(new Rect(10, 20, 150, 20), "Search by name");
        objectsToSearch = GUI.TextField(new Rect(90, 60, 150, 20), objectsToSearch, 25);

        if (objectsToSearch != "")
        {
            GUI.enabled = true;
        }
        else
        {
            GUI.enabled = false;
        }
        GUILayout.Space(40);
        if (GUILayout.Button("Search"))
        {
            foundObjects = new List<GameObject>();
            duplicatedObjects = new List<GameObject>();
            countChildren = true;
            countChilds = 0;
            count = 0;

            foreach (GameObject gameObj in GameObject.FindObjectsOfType<GameObject>())
            {
                if (gameObj.name == objectsToSearch)
                {
                    count += 1;
                    foundObjects.Add(gameObj);
                }
            }

            if (foundObjects.Count > 0)
            {
                searched = true;
            }
            else
            {
                searched = false;
            }
        }

        GUI.enabled = true;
        if (count > 0)
            GUI.TextField(new Rect(90, 85, 60, 15), count.ToString(), 25);

        if (foundObjects.Count > 0 && countChildren == true)
        {
            for (int i = 0; i < foundObjects.Count; i++)
            {
                if (foundObjects[i].transform.childCount > 0)
                {
                    countChilds += foundObjects[i].transform.childCount;
                    //GameObject duplicate = Instantiate(foundObjects[i]);
                    //duplicate.name = foundObjects[i].name;
                    //duplicatedObjects.Add(duplicate);
                }
            }

            countChildren = false;
        }
        GUI.enabled = true;
        if (countChilds > 0)
            GUI.TextField(new Rect(90, 105, 60, 15), countChilds.ToString(), 25);

        GUILayout.Space(100);

        if (foundObjects.Count > 0)
            EditorGUILayout.LabelField("Test");
    }

    private void Replacing()
    {
        GUILayout.Space(20);
        GUILayout.BeginVertical(GUI.skin.box);
        GUILayout.Label("Replacing");
        GUILayout.Space(20);

        prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefab, typeof(GameObject), false);

        var selection = Selection.objects.OfType<GameObject>().ToList();
        if (selectionChanged)
        {
            if (selection.Count == 0)
                GUI.enabled = false;

            for (var i = selection.Count - 1; i >= 0; --i)
            {
                var selectedObject = selection[i];
                if (prefab != null && selection.Count > 0 &&
                    selectedObject.scene.name != null
                    && prefab != PrefabUtility
                    .GetCorrespondingObjectFromSource(selectedObject))
                {
                    GUI.enabled = true;
                }
                else
                {
                    GUI.enabled = false;
                }
            }
        }
        else
        {
            GUI.enabled = false;
        }

        if (GUILayout.Button("Replace"))
        {
            InstantiatePrefab(selection);
            selectionChanged = false;
        }

        GUILayout.Space(10);
        GUI.enabled = true;
        EditorGUILayout.LabelField("Selection count: " + Selection.objects.OfType<GameObject>().Count());

        GUILayout.EndVertical();
    }

    private void OnInspectorUpdate()
    {
        Repaint();
    }

    private void OnSelectionChange()
    {
        selectionChanged = true;
    }

    private void InstantiatePrefab(List<GameObject> selection)
    {
        if (prefab != null && selection.Count > 0)
        {
            for (var i = selection.Count - 1; i >= 0; --i)
            {
                var selected = selection[i];
                SceneManager.SetActiveScene(SceneManager.GetSceneByName(selected.scene.name));

                var prefabType = PrefabUtility.GetPrefabType(prefab);
                GameObject newObject;

                if (prefabType == PrefabType.Prefab)
                {
                    newObject = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                }
                else
                {
                    newObject = Instantiate(prefab);
                    newObject.name = prefab.name;
                }
                if (newObject == null)
                {
                    Debug.LogError("Error instantiating prefab");
                    break;
                }

                Undo.RegisterCreatedObjectUndo(newObject, "Replace With Prefabs");
                newObject.transform.parent = selected.transform.parent;
                newObject.transform.localPosition = selected.transform.localPosition;
                newObject.transform.localRotation = selected.transform.localRotation;
                newObject.transform.localScale = selected.transform.localScale;
                newObject.transform.SetSiblingIndex(selected.transform.GetSiblingIndex());
                Undo.DestroyObjectImmediate(selected);
            }
        }
    }
}

搜索部分在层次结构中找到对象,并且如果有任何子对象,也要对其进行计数。

替换零件用对象选择替换预制件。例如,如果我选择20个立方体并单击“替换”按钮,它将以相同的位置,旋转,缩放立方体的预制替换选定的立方体。

但是,如果有的话,这并不能取代孩子。

搜索时需要某种方式将父项和子项添加到列表中,并保持每个父项及其子项的层次结构,然后单击替换按钮进行替换时,将搜索结果对象,而不是像现在这样的选择,包括孩子们。

如果我的层次结构如下所示的示例:

Cube1
Cube1
Cube1
  Cube1
    Cube1
Cube1

如果我在搜索Cube1,我会找到6个多维数据集,其中两个是孩子。例如,如果我将其替换为Sphere prefab,则层次结构应如下所示:

Sphere
Sphere
Sphere
  Sphere
    Sphere
Sphere

我需要做的是将搜索部分与替换部分组合在一起,并使替换部分也包括孩子。

戴夫

您可以尝试这样的事情:

void ChangeObjectRecursively(Transform t)
{
    for (int i = 0; i < t.childCount; i++)
    {
        ChangeObjectRecursively(t.getChild(i));
    }

    ChangeObject(t.gameObject);
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何用预制件替换游戏对象并将所有组件和组件属性设置添加到预制件中?

如何删除属于预制件的游戏对象而不会损坏预制件?

如何比较预制件和游戏对象?

使用我的方法将预制件实例化为对象

使用具有不同变量值的对象类实例化预制件-Unity

预制件/游戏对象作为相机

销毁对象并在原始对象位置替换为预制件?

如何将 Canvas 中的对象调用到 Unity 预制件中的角色对象?

与对象碰撞时不会激活预制件

在预制件中存储对场景对象的引用?

来自预制件的对象动画存在问题

如何在 ARCore 生成的平面上沿相机视图方向移动对象/预制件

使用自定义基础对象实例化预制件

在编辑过程中用场景中的预制件替换unity3d对象

如何使用 editorwindow 脚本导出预制件的包?

如何将一个特定的预制件/游戏对象及其所有依赖项复制到另一个项目?

如果有嵌套对象,我如何从对象创建数组

如果达到限制则停止实例化预制件,但如果预制件被破坏则继续

如何更改预制件的层次结构

如何正确加载预制件

未实例化的预制预制件与实例化的预制件相比如何?

处理预制件时出现错误“对象引用未设置为对象的实例”

如果有依赖对象,如何将用户放到postgres中

如果有平局,则使用 Java 在对象列表中查找最小数量

使用对象作为数组索引的缺点(如果有)是什么?

在预制件中包括外部解决方案

在触发器内按下操作键后,销毁属于预制件的游戏对象

Unity:在GameObject上实例化预制件-错误对象为null

将预制件作为游戏对象的子代统一生成