如何在搜索栏中对对象进行筛选后,如何对层次结构中的对象进行排序?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在搜索栏中对对象进行筛选后,如何对层次结构中的对象进行排序?相关的知识,希望对你有一定的参考价值。

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

[InitializeOnLoad]
public class CustomHierarchy : MonoBehaviour
{
    private static Vector2 offset = new Vector2(0, 2);
    public static Color gameObjectFontColor = Color.black;
    public static Color prefabOrgFontColor = Color.black;
    public static Color prefabModFontColor = Color.white;
    public static Color inActiveColor = new Color(0.01f, 0.4f, 0.25f);
    public static Color meshRendererColor = Color.yellow;

    static CustomHierarchy()
    {
        EditorApplication.hierarchyWindowItemOnGUI += HandleHierarchyWindowItemOnGUI;
    }
    private static void HandleHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
    {
        Color fontColor = gameObjectFontColor;
        Color backgroundColor = new Color(.76f, .76f, .76f);
        FontStyle styleFont = FontStyle.Normal;
        var obj = EditorUtility.InstanceIDToObject(instanceID);
        GameObject gameObj = EditorUtility.InstanceIDToObject(instanceID) as GameObject;

        if (Selection.instanceIDs.Contains(instanceID))
        {
            backgroundColor = new Color(0.24f, 0.48f, 0.90f);
        }
        if (obj != null)
        {
            var prefabType = PrefabUtility.GetPrefabType(obj);
            if (gameObj.activeInHierarchy == false)
            {
                backgroundColor = inActiveColor;
            }

            if (prefabType == PrefabType.PrefabInstance)
            {
                styleFont = FontStyle.Bold;
                PropertyModification[] prefabMods = PrefabUtility.GetPropertyModifications(obj);
                foreach (PropertyModification prefabMod in prefabMods)
                {
                    if (prefabMod.propertyPath.ToString() != "m_Name" && prefabMod.propertyPath.ToString() != "m_LocalPosition.x" && prefabMod.propertyPath.ToString() != "m_LocalPosition.y" && prefabMod.propertyPath.ToString() != "m_LocalPosition.z" && prefabMod.propertyPath.ToString() != "m_LocalRotation.x" && prefabMod.propertyPath.ToString() != "m_LocalRotation.y" && prefabMod.propertyPath.ToString() != "m_LocalRotation.z" && prefabMod.propertyPath.ToString() != "m_LocalRotation.w" && prefabMod.propertyPath.ToString() != "m_RootOrder" && prefabMod.propertyPath.ToString() != "m_IsActive")
                    {
                        if (HasAllComponents(gameObj, typeof(MeshRenderer), typeof(BoxCollider)))
                        {
                            gameObj.transform.SetSiblingIndex(0);
                            fontColor = meshRendererColor;
                        }
                        else
                        {
                            fontColor = prefabModFontColor;
                        }

                        break;
                    }
                }
                if (fontColor != prefabModFontColor)
                {
                    if (HasAllComponents(gameObj, typeof(MeshRenderer), typeof(BoxCollider)))
                    {
                        gameObj.transform.SetSiblingIndex(0);
                        fontColor = meshRendererColor;
                    }
                    else
                    {
                        fontColor = prefabOrgFontColor;
                    }
                }
            }
            else
            {
                if (HasAllComponents(gameObj, typeof(MeshRenderer), typeof(BoxCollider)))
                {
                    gameObj.transform.SetSiblingIndex(0);
                    fontColor = meshRendererColor;
                }
            }
            Rect offsetRect = new Rect(selectionRect.position + offset, selectionRect.size);
            EditorGUI.DrawRect(selectionRect, backgroundColor);
            EditorGUI.LabelField(offsetRect, obj.name, new GUIStyle()
            {
                normal = new GUIStyleState() { textColor = fontColor },
                fontStyle = styleFont
            }
            );
        }
    }

    public static bool HasAllComponents(GameObject gameObject, params System.Type[] types)
    {
        for (int i = 0; i < types.Length; i++)
        {
            if (gameObject.GetComponent(types[i]) == null)
                return false;
        }

        return true;
    }
}

我在某些地方做过:

gameObj.transform.SetSiblingIndex(0);

它确实在层次结构的主根中工作,有一个黄色的对象,他正在移动到顶部。

但是当我在搜索栏中按名称过滤对象时,例如键入:Corridor有许多对象,但没有一个移动到顶部。我想在我添加的所有地方都是黄色的所有对象:

gameObj.transform.SetSiblingIndex(0);

将移至顶部。因此,例如,如果有30个黄色的对象是HasAllComponents,即使在过滤时也将它们全部移动到顶部。

答案

搜索栏是一个视图过滤器;它对对象层次结构的状态没有影响。 SetSiblingIndex对搜索视图一无所知,因此无法对其中的内容进行重新排序。它只能重新排序共享同一父级的对象。

如果您确实有充分的理由修改对象层次结构并根据搜索结果移动游戏对象,则可以将所有当前选定的对象作为场景层次结构顶部附近的同一容器对象的父级,以便它们首先显示在搜索中,然后可以相对于彼此重新排序。

gameObj.transform.SetParent(someContainerGameObject.transform);

或者您可以编写自己的自定义编辑器窗口,可以按照您想要的顺序进行搜索和显示,而不会影响场景层次结构。

编辑:有关资产搜索的更多信息:

可以在编辑器代码中使用AssetDatabase来搜索整个项目库而不是Scene。即使拥有数千个资产,搜索也非常快,所以这样做是合理的:

AssetDatabase.FindAssets("t:GameObject");

这将为您提供guid字符串,您可以使用AssetDatabase.GUIDToAssetPath()和AssetDatabase.LoadAssetAtPath()将其转换为对象引用。获得GameObject引用后,可以使用HasAllComponents方法检查每个引用。

如果要对它们进行更改,可以a)更新脚本以在需要时自动执行AddComponent之类的操作,或者b)将所有代码包装在新的Editor窗口中,列出这些对象以便在编辑器中轻松选择,或c)您可以通过代码自动创建新选择。

解释每个选项的详细信息超出了本问题的范围,但这应该可以帮助您入门。

以上是关于如何在搜索栏中对对象进行筛选后,如何对层次结构中的对象进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C 中的日期字符串中对字符串日期进行二进制搜索?

如何在 C++ 中对向量组元素进行排序?

如何在CAD中对图纸进行图案填充

如何在 ColdFusion 中对结构数组进行排序

如何在Java中对MongoDB按日期进行查询统计

Navicat 教程:如何进行搜索筛选