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;
}
}
}