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;
using System.IO;
namespace Momiji
{
[InitializeOnLoad]
public class LayerEnumCreator
{
private const string LAYER_ENUM_HASH_KEY = "Layer_Enum_Hash";
[MenuItem("Assets/Creator/LayerEnumCreator")]
public static void _layerNameCreator()
{
if (EditorApplication.isPlaying || Application.isPlaying)
return;
EditorApplication.delayCall += BuildlayerName;
}
static LayerEnumCreator()
{
if (EditorApplication.isPlaying || Application.isPlaying)
return;
EditorApplication.delayCall += BuildlayerName;
}
static void BuildlayerName()
{
System.Text.StringBuilder builder = new System.Text.StringBuilder();
builder = WriteTagManagerClass(builder);
string text = builder.ToString().Replace(",}", "}");
string assetPath = Application.dataPath + EditorExtensionConst.SAVE_FILE_POINT + "LayerEnum.cs";
Directory.CreateDirectory(Application.dataPath + EditorExtensionConst.SAVE_FILE_POINT);
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);
EditorApplication.delayCall -= BuildlayerName;
}
static System.Text.StringBuilder WriteTagManagerClass(System.Text.StringBuilder builder)
{
List<string> layerNames = InternalEditorUtility.layers.ToList();
WriteLayerEnum(builder, layerNames);
return builder;
}
static void WriteLayerEnum(System.Text.StringBuilder builder, List<string> layerNames)
{
builder.AppendLine("/// <summary>");
builder.AppendFormat("/// Access Layer Number Enum").AppendLine();
builder.AppendLine("/// </summary>");
builder.Append("public enum LayerEnum").AppendLine();
builder.AppendLine("{");
layerNames.ForEach((layerName, i) =>
{
var comma = (i == layerNames.Count() - 1) ? "" : ",";
if (i >= 3)
{
i += 1;
if (i >= 6)
{
i += 2;
}
}
builder.Append("\t").AppendFormat(@"{0} = {1}", layerName.SymbolReplace(), i + comma).AppendLine();
});
builder.AppendLine("};");
}
}
}
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
};
}
自作フレームワークに組み込んで改修を続けているのでご興味あれば
https://github.com/MizoTake/MomijiFramework