Наводимо порядок у Hierarchy View!

    
Не так давно розробники Юніті порадували нас новою версією 4.5 (а в 4.6, зовсім скоро, нас чекає новий GUI, ура!), І серед списку змін один пункт стосується сортування у вікні Hierarchy: «sorting of elements is now based on transform order instead of name ».
Що це означає? Ви можете вручну перетягувати елементи у вікні ієрархії в потрібному вам порядку. І якщо раніше ви збирали сцену з розрахунку на автоматичне сортування по імені, то тепер список об'єктів на сцені перетворився на кашу.
 
Ми могли б просто зробити як було… але зробимо краще :)
 
На картинці ви бачите звичну сортування по імені, за винятком трьох допоміжних об'єктів, які розташовуються внизу. Крім того орієнтуватися на складних сценах буде простіше за рахунок колірної диференціації штанів іконок.
 
 
 
Для початку хочу сказати, що Юніті надзвичайно гнучкий інструмент, який ви можете модифікувати за своїм бажанням, або використовувати більше тисячі готових модифікацій . Для цього потрібно писати скрипти з використанням типів, розташованих в просторі імен UnityEditor , а самі скрипти класти в папку Editor (попередньо створивши її).
 
Насамперед подивимося на BaseHierarchySort . Якщо ви працювали з інтерфейсом IComparable в C #, то відразу зрозумієте, як це працює. У Юніті ми повинні створити скрипт, який успадковує від класу BaseHierarchySort і перевизначає метод int Compare (GameObject, GameObject) , в якому ви порівнюєте два об'єкти. Якщо перший повинен йти до другого, метод повинен повернути -1, якщо після — 1, інакше — 0.
У документації рекомендується використовувати готовий метод EditorUtility.NaturalCompare (string, string) , який порівнює два рядки «людським» чином (рахуючи йдуть один за одним цифри одним числом). Таким чином «xx11» йде після «xx2».
Я більше звик до стандартної нелюдської віндовий сортуванні, так що використовую стандартний метод String.Compare (string, string) :
 
 
public class CustomHierarchySorting : BaseHierarchySort
{
	public override int Compare(GameObject lhs, GameObject rhs)
	{
		if (lhs == rhs) return 0;
		if (lhs == null) return -1;
		if (rhs == null) return 1;

		if (lhs.tag == "Auxiliary" && rhs.tag != "Auxiliary")
			return 1;
		if (lhs.tag != "Auxiliary" && rhs.tag == "Auxiliary")
			return -1;

		return String.Compare(lhs.name, rhs.name);
	}
}

 
У моєму прикладі об'єкти з тегом «Auxiliary» при сортуванні опиняться в кінці списку.
 
Як тільки цей скрипт опиниться в папці Editor у вікні Hierarchy з'явиться кнопка, що дозволяє вибрати, який скрипт використовувати для сортування:
 
 
Відмінно, потрібний функціонал ми швидко реалізували в кілька рядків. З іконками буде трохи складніше.
 
На швидку руку я намалював кілька різнокольорових іконок і додав їх в папку «Editor \ Icons»:
 
 
 
 
 
Додавання іконок, як і різні типи сортировок залишили на реалізацію користувачам Юніті, надавши для цього набір методів і подій .
Ми використовуватимемо подію EditorApplication.hierarchyWindowChanged () , яке виникає кожного разу при оновленні вікна ієрархії і EditorApplication.hierarchyWindowItemOnGUI (int, Rect) , який викликається при відображенні елемента у вікні ієрархії, передаючи що підписався методу id елемента і Rect — область отрисовки.
Так само ми будемо використовувати атрибут класу InitializeOnLoad , завдяки якому конструктор класу (в якому ми і передплатимо ці події) буде викликатися автоматично, при запуску Юніті:
 
 
[InitializeOnLoad]
public class HierarchyIcons
{

	static readonly Texture2D Cyan;
	static readonly Texture2D Orange;
	static readonly Texture2D Yellow;
	static readonly Texture2D Gray;

	static readonly List<int> CyanMarked = new List<int>();
	static readonly List<int> OrangeMarked = new List<int>();
	static readonly List<int> YellowMarked = new List<int>();
	static readonly List<int> GrayMarked = new List<int>();

	static HierarchyIcons()
	{
		Cyan = AssetDatabase.LoadAssetAtPath("Assets/Editor/Icons/IconCyan.png", typeof(Texture2D)) as Texture2D;
		Orange = AssetDatabase.LoadAssetAtPath("Assets/Editor/Icons/IconOrange.png", typeof(Texture2D)) as Texture2D;
		Yellow = AssetDatabase.LoadAssetAtPath("Assets/Editor/Icons/IconYellow.png", typeof(Texture2D)) as Texture2D;
		Gray = AssetDatabase.LoadAssetAtPath("Assets/Editor/Icons/IconGray.png", typeof(Texture2D)) as Texture2D;

		EditorApplication.hierarchyWindowChanged += Update;
		EditorApplication.hierarchyWindowItemOnGUI += DrawHierarchyItemIcon;
	}

	static void Update()
	{
		CyanMarked.Clear();
		OrangeMarked.Clear();
		YellowMarked.Clear();
		GrayMarked.Clear();

		GameObject[] go = Object.FindObjectsOfType(typeof(GameObject)) as GameObject[];

		foreach (GameObject g in go)
		{
			if (g == null) continue;

			int instanceId = g.GetInstanceID();

			if (g.tag == "Player")
				OrangeMarked.Add(instanceId);
			else if (g.tag == "Interactive")
				CyanMarked.Add(instanceId);
			else if (g.tag == "Auxiliary")
				YellowMarked.Add(instanceId);
			else
				GrayMarked.Add(instanceId);
		}
	}

	static void DrawHierarchyItemIcon(int instanceId, Rect selectionRect)
	{
		Rect r = new Rect(selectionRect);
		r.x += r.width - 25;
		r.width = 18;

		if (CyanMarked.Contains(instanceId))
			GUI.Label(r, Cyan);
		if (OrangeMarked.Contains(instanceId))
			GUI.Label(r, Orange);
		if (YellowMarked.Contains(instanceId))
			GUI.Label(r, Yellow);
		if (GrayMarked.Contains(instanceId))
			GUI.Label(r, Gray);
	}
}

 
У цьому прикладі при кожному оновленні HierarchyView перезбирати списки об'єктів, що відповідають різним іконка. Для складання цих списків я використовую визначення за тегом, але ви можете використовувати пошук по компонентах об'єкта. Так можна привласнити іконку всіх об'єктах, у яких є Collider з властивістю isTrigger = true, наприклад.
 
Готово!
 
Окремо хочу зауважити, що такі маніпуляції з іконками можуть серйозно позначитися на продуктивності під час роботи в редакторі, особливо якщо ви будете використовувати пошук по компонентах об'єктів. Для тимчасового відключення отрисовки іконок, при необхідності протестувати продуктивність гри, ви могли б додати класу HierarchyIcons статичні методи для підписки / відписки на події відновлення вікна ієрархії.
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.