前々回では、 ColorUsageAttribute により Unity エディタの Inspector ウィンドウで色を設定する GUI をカスタマイズしました。
その際に、Color 型と Color32 型の内部データを確認するためにログ出力を行いました。
任意のタイミングで、Unity エディタから自作コンポーネントのログ出力のメンバ関数を呼び出す際に、 ContextMenu という便利な Attribute で簡単に実装できたので、今回はそれを紹介します。
※ Unity は 2021.3.14f1 です。
ContextMenu Attribute
スクリプトの呼び出したい関数の上に記述するだけで、 Inspector ウィンドウのコンポーネントの枠の右上に…ボタンのプルダウンメニューにメニューアイテムが追加されます。
ContextMenu Attribute にはコンストラクタが 3 つあるので順に紹介します。
public ContextMenu (string itemName);
筆者が前回のログ出力で使ったコンストラクタです。
ログ出力の関数は次の通りです。
[ContextMenu("Log ColorUsageAttribute")] // Inspector のコンポーネント枠の右上の歯車ボタンから選択するメニューを追加し、この関数と紐づけます。
private void LogColorUsageAttribute()
{
Debug.Log("MyColor = " + MyColor);
Debug.Log("MyColor32 = " + MyColor32);
Debug.Log("ColorUsageAttribute1A = " + ColorUsageAttribute1A);
Debug.Log("ColorUsageAttribute1B = " + ColorUsageAttribute1B);
Debug.Log("ColorUsageAttribute2A = " + ColorUsageAttribute2A);
Debug.Log("ColorUsageAttribute2B = " + ColorUsageAttribute2B);
}
関数自体は Debug.Log 関数を使って変数名と変数の値をログ出力しているだけです。
この関数を Unity エディタから呼び出すために付加したものが一行目の Attribute です。
[ContextMenu("メニューアイテム名")]
string itemName にはメニューアイテムに表示される文字列を設定します。
今回は “Log ColorUsageAttribute” を指定しました。
Unity エディタの自作コンポーネントの右上にある…ボタンを押すと、プルダウンメニューの一番下に “Log ColorUsageAttribute” というメニューアイテムが追加されています。
そのメニューアイテムをクリックすると、関数が呼び出されログ出力されました。
Console ウィンドウでログを選択して詳細を見ると、呼び出し元の関数も確認できます。
itemName に / を加えることで、階層を分けられます。
[ContextMenu("My/Log ColorUsageAttribute")]
先ほどのメニューアイテム名の前に「My/」を加えると、上位メニューアイテム [My] の下位に先ほどのメニューアイテム [Log ColorUsageAttribute] が移動しました。
メニューアイテムが増えてきた際のカテゴリ分けなどに便利そうです。
itemName の末尾に %g などと設定するとショートカットキーを割り当てられます。 %g の場合は Ctrl + G をショートカットキーに設定できます。
※ショートカットキーについては次回詳細に解説します。
[ContextMenu("My/Log ColorUsageAttribute %g")]
private void LogColorUsageAttribute()
{
// ...
}
public ContextMenu (string itemName, bool isValidateFunction);
第 2 引数の bool isValidateFunction (デフォルト値は false) は不明でしたが、次回の MenuItem の調べもので使い方がわかりました。
まずはコードを見てください。
// 同じ itemName を持つメニューアイテムの有効性を判定します。戻り値が false だと対応するメニューアイテムは無効の表示になります。
[ContextMenu("My/Test Validate Function 1", true)]
private bool TestContextMenu2Validation()
{
return false;
}
// TestMenuItem2Validation 関数で true の場合のみ選択可能なメニューアイテムです。 false の場合は無効なので関数を呼び出せません。
[ContextMenu("My/Test Validate Function 1", false)]
private void TestContextMenu2()
{
Debug.Log("TestContextMenu2 called.");
}
isValidateFunction 引数が true のメニューアイテムの有効性を返す Validation Function、 isValidateFunction 引数が false のメニューアイテム選択時に呼び出される関数のペアで成り立ちます。
この 2 つの関数の関連付けは ContextMenu の第 1 引数 itemName が同一な場合に行われます。
itemName が同一かつ isValidateFunction が true の関数 (Validation Function) があれば、その関数を呼び出し戻り値を得ます。
Validation Function の戻り値が false の場合、itemName が同一かつ isValidateFunction が false のメニューアイテムは非活性状態になり選択できません。
public ContextMenu (string itemName, bool isValidateFunction, int priority);
第 3 引数の int priority はそのメニューアイテムの優先度を表します。
具体的には、数値が小さいほど Inspector ウィンドウのコンポーネントの枠の右上にある…ボタンを押すと出てくるプルダウンメニューで上の方に表示されます。
デフォルト値は 1000000 です。
次のコードを追記しました。
[ContextMenu("TestContextMenuPriority100", false, 100)]
private void TestContextMenuPriority100()
{
Debug.Log("TestContextMenuPriority100 called.");
}
Unity エディタの Inspector ウィンドウの自作コンポーネントの枠の右上の…ボタンを押し、プルダウンメニューを見ると、 priority を指定していないメニューアイテムよりも少し上の方にメニューアイテムが追加されました。
itemName に上位メニューアイテム [My] を加えて試してみました。
[ContextMenu("My/TestContextMenuPriority100", false, 100)]
上位メニューアイテムの My ごと優先度が高くなり、上位メニューアイテム My ごとプルダウンメニューの上の方に移動しました。
下位のメニューでは priority を指定したメニューアイテムが上側に表示され、指定していないメニューアイテムは線で仕切られています。
MenuItem Attribute との違い
Unity エディタにメニューアイテムを追加し、関数を呼び出す属性には ContextMenu の他に MenuItem があります。
MenuItem はメニューバーにメニューアイテムを追加することができるなど様々な違いがありますが、重要な違いの一つして、 ContextMenu はメンバ関数を呼ぶことができ、 MenuItem は静的関数を呼ぶことができることが挙げられます。
メンバ変数を参照する場合は、 ContextMenu の方が適しています。
まとめ
今回は自作コンポーネントの関数を Unity エディタ上から簡単に呼び出す ContextMenu Attribute について紹介しました。
isValidateFunction によってメニューアイテムの有効無効を変更したり、Inspector ウィンドウのコンポーネントのプルダウンメニューに簡単にメニューアイテムを追加でき、階層分けやメニューアイテムの順番の変更ができました。
コメント