0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Unity] SortingLayerの使用状況を一覧表示するエディタ拡張

Last updated at Posted at 2023-07-27

SortingLayerの使用状況を一覧で確認する方法がないか調たんですが、それっぽい機能がどこにもなさそうだったので自作しました。

  • 仕様
    「Renderer継承クラス(SpriteRendererなど)」「Canvas」を含むGameObjectを抽出して検索します。Sorting Layerに関連するクラスはこれでほぼ網羅できていると思いますが、ヌケモレあったら教えてください!

  • 使い方
    メニューの「UnmoEngineTools/Sorting Layer Finder」から実行できます。

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

namespace EditorScript
{
	/// <summary>
	/// エディタ拡張
	/// アセット全体/Hierarchy全体のGameObjectに対して、SortingLayer使用状況を一括検索
	/// メニュー選択した時点で検索開始するので、その間はUnityエディタが一時フリーズした感じになる
	/// </summary>
	public class SortingLayerFinder : EditorWindow
	{
		private Dictionary<string, List<string>> matchedObjectsPerLayer = new Dictionary<string, List<string>>();
		private List<Type> rendererTypes = new List<Type>();
		private Vector2 scrollPosition = Vector2.zero;

		[MenuItem("UnmoEngineTools/Sorting Layer Finder")]
		public static void Open()
		{
			var window = GetWindow<SortingLayerFinder>();
			window.Show();
		}

		private void OnEnable()
		{
			// Rendererの継承クラスを全て取得
			rendererTypes = AppDomain.CurrentDomain
				.GetAssemblies()
				.SelectMany(a => a.GetTypes())
				.Where(t => t.IsSubclassOf(typeof(Renderer)))
				.ToList();
			
			// 全てのSortingLayerに対して検索開始
			SortingLayer.layers
				.Select(layer => layer.name)
				.ToList()
				.ForEach(layerName => FindObjectsWithSortingLayer(layerName));
		}

		private void OnGUI()
		{
			// スクロールビュー追加
			scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
			
			// 各SortingLayerに対する結果を表示
			var style = new GUIStyle(EditorStyles.label);
			style.richText = true;
			foreach (var pair in matchedObjectsPerLayer)
			{
				EditorGUILayout.LabelField($"<b><color=green>Sorting Layer: {pair.Key}</color></b>", style);
				foreach (var matchedObject in pair.Value)
				{
					EditorGUILayout.LabelField(matchedObject);
				}

				EditorGUILayout.Space();
			}

			// スクロールビュー終了
			EditorGUILayout.EndScrollView();
		}

		private void FindObjectsWithSortingLayer(string sortingLayerName)
		{
			// SortingLayer毎の結果格納用リスト
			matchedObjectsPerLayer[sortingLayerName] = new List<string>();

			// Asset内のPrefabに対して検索
			string[] guids = AssetDatabase.FindAssets("t:Prefab");
			foreach (var guid in guids)
			{
				string assetPath = AssetDatabase.GUIDToAssetPath(guid);
				GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
				if (HasComponentWithSortingLayer(prefab, sortingLayerName))
				{
					matchedObjectsPerLayer[sortingLayerName].Add(assetPath);
				}
			}

			// Hierarchy内のGameObjectに対して検索
			GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>();
			foreach (var obj in allObjects)
			{
				if (HasComponentWithSortingLayer(obj, sortingLayerName))
				{
					string objectPath = GetGameObjectPath(obj.transform);
					matchedObjectsPerLayer[sortingLayerName].Add(objectPath);
				}
			}
		}

		private bool HasComponentWithSortingLayer(GameObject obj, string sortingLayerName)
		{
			// Renderer継承クラス
			if (rendererTypes.Any(t => HasComponentWithSortingLayerOfType(obj, t, sortingLayerName)))
			{
				return true;
			}

			// Canvas
			return HasComponentWithSortingLayerOfCanvas(obj, sortingLayerName);
		}

		private bool HasComponentWithSortingLayerOfType(GameObject obj, Type type, string sortingLayerName)
		{
			return obj.GetComponentsInChildren(type, true)
				.Cast<Renderer>() // typeはRendererのサブクラスのみであることが保証されているので、キャスト可能
				.Any(component => component.sortingLayerName == sortingLayerName);
		}

		private bool HasComponentWithSortingLayerOfCanvas(GameObject obj, string sortingLayerName)
		{
			return obj.GetComponentsInChildren<Canvas>(true)
				.Any(component => component.sortingLayerName == sortingLayerName);
		}
				
		private string GetGameObjectPath(Transform transform)
		{
			string path = transform.name;
			while (transform.parent != null)
			{
				transform = transform.parent;
				path = transform.name + "/" + path;
			}

			return path;
		}
	}
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?