Unity ContextMenu でメニューからメンバ関数を呼び出す

前々回では、 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” というメニューアイテムが追加されています。

ContextMenu 属性によりコンポーネントのプルダウンにメニューアイテムが追加されました。

そのメニューアイテムをクリックすると、関数が呼び出されログ出力されました。
Console ウィンドウでログを選択して詳細を見ると、呼び出し元の関数確認できます。

Unity ContextMenu で関連付けたログ出力関数が呼び出されました。

itemName に / を加えることで、階層を分けられます

[ContextMenu("My/Log ColorUsageAttribute")]

先ほどのメニューアイテム名の前に「My/」を加えると、上位メニューアイテム [My]下位に先ほどのメニューアイテム [Log ColorUsageAttribute] が移動しました。
メニューアイテムが増えてきた際のカテゴリ分けなどに便利そうです。

Unity ContextMenu の itemName をスラッシュで区切ると上位メニューの中にさきほどのメニューが移動しました。

itemName の末尾に %g などと設定するとショートカットキーを割り当てられます。 %g の場合は Ctrl + G をショートカットキーに設定できます。
※ショートカットキーについては次回詳細に解説します。

[ContextMenu("My/Log ColorUsageAttribute %g")]
private void LogColorUsageAttribute()
{
    // ...
}
Unity ContextMenu の itemName の末尾に %g などをつけるとショートカットキーを設定できます。

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 のメニューアイテムは非活性状態になり選択できません

Unity ContextMenu の Validation Function が false を返すと同一の itemName を持つメニューアイテムは非活性になります。

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 を指定していないメニューアイテムよりも少し上の方にメニューアイテムが追加されました。

Unity ContextMenu(priority=100)の場合、指定しないメニューアイテムより上の方に表示されました。

itemName に上位メニューアイテム [My] を加えて試してみました。

[ContextMenu("My/TestContextMenuPriority100", false, 100)]

上位メニューアイテムの My ごと優先度が高くなり、上位メニューアイテム My ごとプルダウンメニューの上の方に移動しました。
下位のメニューでは priority を指定したメニューアイテムが上側に表示され、指定していないメニューアイテムは線で仕切られています。

Unity ContextMenu(priority=100)の場合、指定しないメニューアイテムより上位メニューアイテムごと上の方に移動しました。

MenuItem Attribute との違い

Unity エディタにメニューアイテムを追加し、関数を呼び出す属性には ContextMenu の他に MenuItem があります。
MenuItem はメニューバーにメニューアイテムを追加することができるなど様々な違いがありますが、重要な違いの一つして、 ContextMenu はメンバ関数を呼ぶことができ、 MenuItem は静的関数を呼ぶことができることが挙げられます。
メンバ変数を参照する場合は、 ContextMenu の方が適しています。

まとめ

今回は自作コンポーネントの関数を Unity エディタ上から簡単に呼び出す ContextMenu Attribute について紹介しました。
isValidateFunction によってメニューアイテムの有効無効を変更したり、Inspector ウィンドウのコンポーネントのプルダウンメニューに簡単にメニューアイテムを追加でき、階層分けやメニューアイテムの順番の変更ができました。

参照サイト Thank You!

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました