UnityのlayerをenumにしてくれるEditor拡張を作った
たまにしてる、自分のQiita記事転載です(ブログ更新と言いたい)
GameObjectのTag管理を楽にしたくて調べてたら、これをみつけました。
UnityEditorInternal.InternalEditorUtilityを使う - けいごのなんとか
Tagを扱いやすくするクラスの自動生成…なんと甘美な響き…!! 結構前の記事ではありますがUnity5.6.3とかでも動作してくれるので、すごく助かります。
…ここでTagだけでなくLayerも扱いやすくできれば…どうせならEnumに…と思いまして、上記の記事のクラス自動生成を見よう見まねでLayerからEnumスクリプトの自動生成を作ってみました。
using UnityEngine; using UnityEditor; using System.Linq; using UnityEditorInternal; using System.Collections.Generic; using System; [InitializeOnLoad] public class LayerEnumCreator { private const string LAYER_ENUM_HASH_KEY = "Layer_Enum_Hash"; [MenuItem("Assets/LayerEnumCreator")] public static void _layerNameCreator () { if (EditorApplication.isPlaying || Application.isPlaying) return; BuildlayerName (); } static LayerEnumCreator () { if (EditorApplication.isPlaying || Application.isPlaying) return; BuildlayerName (); } static void BuildlayerName () { System.Text.StringBuilder builder = new System.Text.StringBuilder (); builder = WriteTagManagerClass (builder); string text = builder.ToString ().Replace (",}", "}"); string assetPath = currentFolderPath + "../LayerEnum.cs"; if (AssetDatabase.LoadAssetAtPath (assetPath.Replace ("/Editor/..", ""), typeof(UnityEngine.Object)) != null && EditorPrefs.GetInt (LAYER_ENUM_HASH_KEY, 0) == text.GetHashCode ()) return; System.IO.File.WriteAllText (assetPath, text); EditorPrefs.SetInt (LAYER_ENUM_HASH_KEY, text.GetHashCode ()); AssetDatabase.Refresh (ImportAssetOptions.ImportRecursive); } static System.Text.StringBuilder WriteTagManagerClass (System.Text.StringBuilder builder) { List<string> layerNames = InternalEditorUtility.layers.ToList(); builder.AppendLine ("public class LayerEnum"); builder.AppendLine ("{"); { WriteLayerEnum (builder, layerNames); } builder.AppendLine ("}"); return builder; } static void WriteLayerEnum (System.Text.StringBuilder builder, List<string> layerNames) { builder.Append ("\t").AppendLine ("/// <summary>"); builder.Append ("\t").AppendFormat ("/// Access Layer Number Enum").AppendLine (); builder.Append ("\t").AppendLine ("/// </summary>"); builder.Append("\t").Append ("public enum Layer {").AppendLine (); layerNames.ForEach ((layerName, i) => { var comma = (i == layerNames.Count() - 1)? "" : ","; if(i >= 3) { i += 1; if (i >= 6) { i += 2; } } builder.Append("\t").Append("\t").AppendFormat (@"{0} = {1}", layerName.SymbolReplace(), i + comma).AppendLine(); }); builder.Append("\t").AppendLine ("};"); } static string currentFolderPath { get { string currentFilePath = new System.Diagnostics.StackTrace (true).GetFrame (0).GetFileName (); return "Assets" + currentFilePath.Substring (0, currentFilePath.LastIndexOf ("/") + 1).Replace (Application.dataPath, string.Empty); } } }
UnityのEditorの方でLayerの3, 6, 7は入力ができず空白なのでenumに含めず、スキップする処理にしてますが…あまり気に入ってないです… あと、実はこれだけでは動かないです。クラス拡張も行なっているので…
using UnityEngine; using System.Linq; using System.Collections.Generic; using System; public static class ClassExtension { public static string SymbolReplace(this string name) { string[] invalidChar = new string[] {" ", " ", "!", "\"", "#", "$", "%", "&", "\'", "(", ")", "-", "=", "^", "~", "¥", "|", "[", "{", "@", "`", "]", "}", ":", "*", ";", "+", "/", "?", ".", ">", ",", "<"}; invalidChar.ToList ().ForEach (s => name = name.Replace (s, string.Empty)); return name; } public static void ForEach<T> (this IEnumerable<T> collection, Action<T, int> action) { int i = 0; foreach (T t in collection) { action (t, i++); } } }
この拡張を加えれば動くと思います。 ただ、注意点なのはLayerは8から入力できますが、8を入力せず9を入力すると番号がズレるため、その辺は ご自分でよしなにお願いします。 初めての自動生成スクリプト(見よう見まね)なのでツッコミ所があれば突っ込んでいただければと思います。
デフォルトの結果だとこうなります。
public class LayerEnum { /// <summary> /// Access Layer Number Enum /// </summary> public enum Layer { Default = 0, TransparentFX = 1, IgnoreRaycast = 2, Water = 4, UI = 5 }; }