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