Unityでゲーム開発を進めると、多数のタグやレイヤーを設定する必要があることはよくあります。特に中規模以上のプロジェクトでは、タグ・レイヤーの管理が煩雑になりがちです。この記事では、エディタ拡張を活用してタグとレイヤーを一括で登録する方法を紹介します。
この記事を読むと、以下のことができるようになります:
Unity エディタ拡張(Editor Extensions)は、Unity の開発環境自体をカスタマイズし、プロジェクト固有の機能を追加するための仕組みです。エディタ拡張を使うことで、次のメリットが得られます:
エディタ拡張スクリプトは通常、Editor
という特別なフォルダ内に配置され、これらのスクリプトはビルドされたゲームには含まれません。つまり、開発効率を向上させるための機能を、最終製品のサイズやパフォーマンスに影響を与えることなく実装できます。
以下は、タグとレイヤーを一括で登録するためのエディタ拡張スクリプトです。このスクリプトをプロジェクトに追加すると、Unity メニューから簡単にタグとレイヤーを設定できるようになります。
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
public class TagLayerSetupWizard : EditorWindow
{
[MenuItem("Tools/Setup Tags and Layers")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(TagLayerSetupWizard));
}
void OnGUI()
{
GUILayout.Label("タグとレイヤーの一括セットアップ", EditorStyles.boldLabel);
if (GUILayout.Button("タグとレイヤーを設定"))
{
SetupTagsAndLayers();
}
}
void SetupTagsAndLayers()
{
// カスタムタグのリスト
string[] customTags = new string[]
{
"Ball", "Flipper", "Plunger", "Wall", "Target",
"FireTarget", "IceTarget", "LightningTarget", "EarthTarget", "WindTarget",
"Bumper", "Ramp", "Gate", "Dragon", "Collectible",
"Trigger", "DeadZone", "MultiballSpawner", "SpecialZone", "BonusArea"
};
// カスタムレイヤーのリスト
string[] customLayers = new string[]
{
"Ball", "PinballElements", "Flippers", "Plunger", "Walls",
"Targets", "DragonElements", "Triggers", "SpecialEffects", "Background",
"InteractiveElements", "NonColliding", "PlayerOnly", "CameraIgnore", "PostProcess",
"MiniGame", "DragonVisuals", "ElementalEffects", "Physics2D", "Physics3D",
"DynamicObjects", "StaticObjects", "Debugging", "SensorOnly", "NonInteractive",
"CinematicElements", "HiddenInGame"
};
// タグの追加
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
SerializedProperty tagsProp = tagManager.FindProperty("tags");
foreach (string tag in customTags)
{
bool found = false;
for (int i = 0; i < tagsProp.arraySize; i++)
{
SerializedProperty t = tagsProp.GetArrayElementAtIndex(i);
if (t.stringValue.Equals(tag)) { found = true; break; }
}
if (!found)
{
tagsProp.arraySize++;
SerializedProperty newTag = tagsProp.GetArrayElementAtIndex(tagsProp.arraySize - 1);
newTag.stringValue = tag;
}
}
// レイヤーの追加
SerializedProperty layersProp = tagManager.FindProperty("layers");
for (int i = 0; i < customLayers.Length; i++)
{
// レイヤー8-31のみカスタム可能
int layerIndex = 8 + i;
if (layerIndex >= 32) break; // Unity は最大32レイヤーまで
SerializedProperty layerProp = layersProp.GetArrayElementAtIndex(layerIndex);
if (string.IsNullOrEmpty(layerProp.stringValue))
{
layerProp.stringValue = customLayers[i];
}
}
tagManager.ApplyModifiedProperties();
Debug.Log("タグとレイヤーを設定しました");
}
}
実際にこのツールを使うための手順を見ていきましょう。
Editorフォルダの作成: プロジェクト内に Editor
フォルダを作成します。このフォルダはAssets直下でも、任意のサブフォルダ内でも構いません。
Assets/Editor/
または
Assets/_Project/Scripts/Editor/
スクリプトの作成: 上記のスクリプトを TagLayerSetupWizard.cs
という名前で Editor
フォルダ内に保存します。
スクリプトの実行: Unity上部のメニューバーに新しく Tools
メニューが追加され、その中に Setup Tags and Layers
という項目が表示されます。このメニューをクリックすると、ウィンドウが開きます。
タグとレイヤーの設定: ウィンドウ内の「タグとレイヤーを設定」ボタンをクリックすると、コード内で定義したタグとレイヤーが自動的に追加されます。
このスクリプトがどのように動作するのか、主要な部分を解説します:
[MenuItem("Tools/Setup Tags and Layers")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(TagLayerSetupWizard));
}
MenuItem
属性を使用して、Unityメニューバーに新しい項目を追加しています。ここでは Tools
メニュー内に Setup Tags and Layers
という項目を作成しています。
void OnGUI()
{
GUILayout.Label("タグとレイヤーの一括セットアップ", EditorStyles.boldLabel);
if (GUILayout.Button("タグとレイヤーを設定"))
{
SetupTagsAndLayers();
}
}
OnGUI
メソッドはエディタウィンドウの描画を担当します。ここではシンプルなラベルとボタンを配置しています。
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
Unity のタグとレイヤーは ProjectSettings/TagManager.asset
ファイルに保存されています。このファイルを SerializedObject
として読み込み、プログラムから操作できるようにしています。
SerializedProperty tagsProp = tagManager.FindProperty("tags");
// 中略
tagsProp.arraySize++;
SerializedProperty newTag = tagsProp.GetArrayElementAtIndex(tagsProp.arraySize - 1);
newTag.stringValue = tag;
タグマネージャーの "tags" プロパティにアクセスし、配列のサイズを増やして新しいタグを追加しています。ただし、既存のタグと重複しないように事前にチェックを行います。
SerializedProperty layersProp = tagManager.FindProperty("layers");
// 中略
SerializedProperty layerProp = layersProp.GetArrayElementAtIndex(layerIndex);
if (string.IsNullOrEmpty(layerProp.stringValue))
{
layerProp.stringValue = customLayers[i];
}
レイヤーも同様にアクセスしますが、Unityでは8〜31の範囲のみカスタムレイヤーとして設定可能です。また、既に設定されているレイヤーは上書きしないように条件分岐を設けています。
tagManager.ApplyModifiedProperties();
最後に、変更内容を確定して保存します。
タグとレイヤーを設定した後、多くの場合はレイヤー間の物理衝突マトリックスも設定する必要があります。これも同様にエディタ拡張で自動化可能です。
以下は、物理衝突マトリックスを設定するメソッドの例です:
void SetupPhysicsLayerCollisions()
{
// Ball レイヤーは特定のレイヤーとのみ衝突
int ballLayer = LayerMask.NameToLayer("Ball");
int pinballElementsLayer = LayerMask.NameToLayer("PinballElements");
int flippersLayer = LayerMask.NameToLayer("Flippers");
int wallsLayer = LayerMask.NameToLayer("Walls");
// 全てのレイヤー間の衝突をオフにする(デフォルトは衝突する)
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
// 必要に応じてレイヤー間の衝突を制御
// Physics.IgnoreLayerCollision(i, j, true); // 衝突を無視
}
}
// 特定のレイヤー間の衝突を有効にする
Physics.IgnoreLayerCollision(ballLayer, pinballElementsLayer, false); // 衝突を有効
Physics.IgnoreLayerCollision(ballLayer, flippersLayer, false);
Physics.IgnoreLayerCollision(ballLayer, wallsLayer, false);
Debug.Log("物理衝突マトリックスを設定しました");
}
このメソッドを SetupTagsAndLayers
メソッドの最後に呼び出すことで、タグとレイヤーの設定と同時に物理衝突マトリックスも設定できます。
物理衝突マトリックスを設定する際のポイント:
デフォルト設定を検討: すべてのレイヤーが互いに衝突するのがデフォルトですが、パフォーマンスを考慮して必要な衝突のみを有効にする「ホワイトリスト方式」も検討しましょう。
論理的なグループ化: 関連するオブジェクトは同じレイヤーに配置し、グループ単位で衝突制御を考えましょう。
頻繁に変更するレイヤーには注意: 実行時に頻繁に変更するレイヤーの衝突設定は慎重に行いましょう。
このエディタ拡張は、さらに以下のように発展させることができます:
タグやレイヤーをコード内のハードコーディングではなく、エディタウィンドウのGUIから動的に追加・削除できるようにします:
private List<string> customTags = new List<string>();
private string newTagName = "";
void OnGUI()
{
GUILayout.Label("タグ設定", EditorStyles.boldLabel);
// 新規タグの入力欄
newTagName = EditorGUILayout.TextField("新規タグ名:", newTagName);
if (GUILayout.Button("タグを追加") && !string.IsNullOrEmpty(newTagName))
{
customTags.Add(newTagName);
newTagName = "";
}
// タグリストの表示
EditorGUILayout.LabelField("登録予定のタグ:");
for (int i = 0; i < customTags.Count; i++)
{
EditorGUILayout.BeginHorizontal();
customTags[i] = EditorGUILayout.TextField(customTags[i]);
if (GUILayout.Button("削除", GUILayout.Width(60)))
{
customTags.RemoveAt(i);
break;
}
EditorGUILayout.EndHorizontal();
}
// 実行ボタン
if (GUILayout.Button("タグを登録"))
{
SetupTagsAndLayers();
}
}
プロジェクトごとに異なるタグ・レイヤー設定をプリセットとして保存し、必要に応じて読み込めるようにします:
[System.Serializable]
public class TagLayerPreset
{
public string presetName;
public List<string> tags = new List<string>();
public List<string> layers = new List<string>();
}
private List<TagLayerPreset> presets = new List<TagLayerPreset>();
private int selectedPresetIndex = 0;
// プリセットの保存と読み込み機能
void SavePreset(string presetName)
{
TagLayerPreset preset = new TagLayerPreset();
preset.presetName = presetName;
preset.tags = new List<string>(customTags);
preset.layers = new List<string>(customLayers);
presets.Add(preset);
// プリセットをJSON形式で保存
string json = JsonUtility.ToJson(new PresetContainer { presets = presets });
EditorPrefs.SetString("TagLayerPresets", json);
}
void LoadPresets()
{
string json = EditorPrefs.GetString("TagLayerPresets", "");
if (!string.IsNullOrEmpty(json))
{
PresetContainer container = JsonUtility.FromJson<PresetContainer>(json);
presets = container.presets;
}
}
[System.Serializable]
private class PresetContainer
{
public List<TagLayerPreset> presets = new List<TagLayerPreset>();
}
複数のプロジェクト間でタグとレイヤーの設定を共有できるようにします:
// プリセットのエクスポート
void ExportPreset(TagLayerPreset preset)
{
string path = EditorUtility.SaveFilePanel(
"プリセットをエクスポート",
"",
preset.presetName + ".json",
"json");
if (!string.IsNullOrEmpty(path))
{
string json = JsonUtility.ToJson(preset);
System.IO.File.WriteAllText(path, json);
Debug.Log("プリセットをエクスポートしました: " + path);
}
}
// プリセットのインポート
void ImportPreset()
{
string path = EditorUtility.OpenFilePanel(
"プリセットをインポート",
"",
"json");
if (!string.IsNullOrEmpty(path))
{
string json = System.IO.File.ReadAllText(path);
TagLayerPreset preset = JsonUtility.FromJson<TagLayerPreset>(json);
presets.Add(preset);
Debug.Log("プリセットをインポートしました: " + preset.presetName);
}
}
タグとレイヤーの一括登録ツールを実装する際のチェックリスト:
Editor
フォルダが正しく作成されているUnity エディタ拡張を活用することで、タグとレイヤーの設定という単調な作業を自動化し、プロジェクト設定の一貫性を保てるようになります。さらに、この記事で紹介した手法は、タグとレイヤー以外のプロジェクト設定にも応用可能です。
エディタ拡張は以下の場面で特に効果を発揮します:
Unity のエディタ拡張機能は非常に強力で、自分たちのワークフローに合わせたカスタマイズが可能です。ぜひ、自分のプロジェクトに合わせたエディタ拡張ツールを開発してみてください。
この記事は、Unity 2020.3以上を基準に作成されています。新しいバージョンでは設定方法が異なる場合があります。