使用InitializeOnLoad时,该问题一直无效。 然后,即使我在脚本顶部为列表创建一次实例,它也会一直为它创建实例,并将越来越多的项目添加到列表中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public static class CustomHierarchy
{
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;
public static List<GameObject> gameobjectsHasAll = new List<GameObject>();
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)))
{
if (!gameobjectsHasAll.Contains(gameObj))
gameobjectsHasAll.Add(gameObj);
fontColor = meshRendererColor;
}
else
{
fontColor = prefabModFontColor;
}
break;
}
}
if (fontColor != prefabModFontColor)
{
if (HasAllComponents(gameObj, typeof(MeshRenderer), typeof(BoxCollider)))
{
gameobjectsHasAll.Add(gameObj);
fontColor = meshRendererColor;
}
else
{
fontColor = prefabOrgFontColor;
}
}
}
else
{
if (HasAllComponents(gameObj, typeof(MeshRenderer), typeof(BoxCollider)))
{
gameobjectsHasAll.Add(gameObj);
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;
}
}
List变量是:
public static List<GameObject> gameobjectsHasAll = new List<GameObject>();
例如,在每个具有HasAllComponents的位置的代码中的3个地方,我将对象添加到列表中:
if (HasAllComponents(gameObj, typeof(MeshRenderer), typeof(BoxCollider)))
{
gameobjectsHasAll.Add(gameObj);
fontColor = meshRendererColor;
}
在层次结构中,我有6个满足HasAllComponents条件的项目。 但是列表第一次包含36个项目时,它会连续6次添加6个项目。
然后接下来的120个左右项目将不停地添加相同的项目。 我从另一个脚本EditorWindow脚本调用此列表:
using System;
using UnityEditor;
using UnityEngine;
using System.Collections;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
public class HierarchyEditor : EditorWindow
{
public static bool multipleComponents = false;
public static string multipleComponentsString = "";
private static SearchableEditorWindow hierarchy { get; set; }
private string filterText = "";
private string oldFilterText = "";
[MenuItem("Tools/Hierarchy Editor")]
public static void ShowWindow()
{
GetWindow<HierarchyEditor>("HierarchyEditor");
Test();
}
测试在哪里
private static void Test()
{
var all = CustomHierarchy.gameobjectsHasAll;
}
答案 0 :(得分:1)
在所有行之前
gameobjectsHasAll.Add(gameObj);
检查对象是否已在列表中,仅在尚不存在时添加它
if(!gameobjectsHasAll.Contains(gameObj))
{
gameobjectsHasAll.Add(gameObj);
fontColor = meshRendererColor;
}
到目前为止,您似乎只检查了一次。
答案 1 :(得分:1)
我相信,在将其分配给EditorApplication.hierarchyWindowItemOnGUI委托时,您只需处理HandleHierarchyWindowItemOnGUI方法中的一个元素。手册说:“为HierarchyWindow中的每个可见列表项目委托OnGUI事件。” (https://docs.unity3d.com/ScriptReference/EditorApplication-hierarchyWindowItemOnGUI.html),因此对于每个列表元素(您有6个),它将再次为每个元素调用它。这是一个统一的生命周期(https://docs.unity3d.com/Manual/ExecutionOrder.html),您会看到它不断调用OnGUI(),因此当您列出的是静态实例时,原因是它不会从中删除先前的对象,因此会作为OnGUI()处理列表并创建通过检查的新实例,列表会越来越大。
因此,您可能想在再次处理它之前清除HandleHierarchyWindowItemOnGUI方法中的列表。