如何在两个场景中循环遍历层次结构中的所有游戏对象,包括禁用对象以及所有子对象?

时间:2019-10-05 18:19:05

标签: c# unity3d

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class CompareObjects : EditorWindow
{
    string searchString = "";
    List<GameObject> items = FindObjectsOfType(typeof(GameObject)).ToList();

    void OnGUI()
    {
        GUILayout.BeginHorizontal(EditorStyles.toolbar);
        GUILayout.FlexibleSpace();
        searchString = GUILayout.TextField(searchString, EditorStyles.toolbarTextField);
        GUILayout.EndHorizontal();

        // Do comparison here. For example
        for (int i = 0; i < items.Length; i++)
        {
            if (items[i].name.Contains(searchString))
            {
                GUI.Label(items[i].name);
            }
        }
    }
}

第一个问题是我无法转换以下数组:

FindObjectsOfType(typeof(GameObject))

要列出。

第二,如何在两个场景中循环播放对象?我想在场景a和场景b对象之间进行比较,并且还能够缩小对具有特定组件的对象的搜索,并在EditorWindow中列出结果:在场景A和列表B中列出具有组件的对象A场景B中具有组件的物体

例如,如果我在搜索栏中输入:Space,BoxCollider 然后,它应该在两个场景中找到所有包含名称Space的对象,这些对象还附加或不附加BoxCollider。

我想在结果中知道哪些名称为Space的对象具有boxcollider,而没有。

示例:

List A : Space1 BoxCollider -- Scene A
List A : Space2 Empty -- Scene A

List B : Space1 Empty -- Scene B
List B : Space2 BoxCollider -- Scene B

类似这样的比较。

1 个答案:

答案 0 :(得分:1)

  

我无法转换

的数组

方法FindObjectsOfType(Type)返回对象数组,可以使用LINQ方法OfType将对象转换为列表:

List<GameObject> items = FindObjectsOfType(typeof(GameObject)).OfType<GameObject>.ToList();

或者只使用方法FindObjectsOfType<T>()的通用替代

List<GameObject> items = GameObject.FindObjectsOfType<GameObject>().ToList();
  

第二,如何在两个场景中循环显示对象?

您需要从SceneManager中选择所有场景,然后在GetRootGameObjects()上进行循环。

如果需要循环所有对象并进行一些手动计算-您可以像described here一样手动织机。如果您知道确切需要什么组件,则可以对场景根对象使用方法public Component[] GetComponentsInChildren(Type t, bool includeInactive);(请确保将includeInactive设置为True,如果要搜索不活动的对象)

  

我想在结果中知道哪些名称为Space的对象具有boxcollider,而没有。

using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

public static class Searcher
{
    [MenuItem("Tools/PrintSearch")]
    public static void PrintSearch()
    {
        var objectName = "Space";
        var componentType = typeof(BoxCollider);

        var scenes = Enumerable.Range(0, SceneManager.sceneCount)
            .Select(SceneManager.GetSceneAt)
            .ToArray();
        var objectsWithNames = scenes
            .ToDictionary(s => s, s=> GetSceneObjectsWithName(s, objectName.ToLower()));

        var forLog = objectsWithNames
            .SelectMany(pair => pair.Value.Select(child =>
                $"Scene {pair.Key.name}: object name '{child.gameObject.name}' {(child.GetComponent(componentType) != null ? "contains" : "do not contains")} component {componentType.Name}"));

        Debug.Log(string.Join("\n", forLog));
    }

    private static Transform[] GetSceneObjectsWithName(Scene scene, string objectName)
    {
        return scene.GetRootGameObjects()
            .SelectMany(g => GetChildHierarchyRecursively(g.transform))
            .Where(t=>t.gameObject.name.ToLower().Contains(objectName))
            .ToArray();
    }

    private static IEnumerable<Transform> GetChildHierarchyRecursively(Transform parentTransform)
    {
        yield return parentTransform;
        if (parentTransform.childCount > 0)
            yield return parentTransform;
    }
}