C++幼女先輩

プログラミング成分多め

UNITY メニュー拡張 part1

コード
https://github.com/YukiMiyatake/UnityLesson/tree/MenuItem_1

はじめに

UNITYでは、インスペクターやメニューを簡単に拡張できる
エディタ拡張により開発効率も大幅に上げる事が可能である
面倒でもこの手の機能は初期に作っておけば、その後の開発期間が大幅に短縮される事が多い
そのため、ぜひとも覚えておきたい

メニュー拡張基本

f:id:murasame-labo:20171015190149p:plain 上記のように メニューにオリジナルの項目を追加できる
メニューは階層化出来、メニュー選択でウインドウ表示することが多い
まず、インスペクタやメニュー等の拡張を エディタ拡張と呼び
Editorフォルダ以下にスクリプトを置く必要がある

メニューの場合は クラスメソッド(static関数)に MenuItemアトリビュートをつければいい

Assets/Menu/Editor/TestMenu.cs

using UnityEngine;
using UnityEditor;

public class TestMenu
{
    [MenuItem("Test/Menu %a")]
    public static void ShowMenu()
    {
        Debug.Log("ShowMenu");
    }
}

MenuItemの第一引数に メニューの階層を指定する。
また、文字列に %a などを入れると、ショートカットキーを設定できる
そのあたりの詳細は是非マニュアルを見て欲しい

Unity - スクリプトリファレンス: MenuItem

非常に簡単にメニュー拡張が出来た

MenuItemの引数

MenuItemは3つの引数をもてる
第一引数はString型。メニューの項目名で、ショートカットキーも設定できる
第三引数はint型。表示の優先度

問題が第二引数
同じ名前のメニュー項目がある場合、メニュー表示時に第二引数がtrueのものが先に呼ばれ
falseを返すとそのメニュー項目はDisableになり、trueの場合はEnableになりクリックするともう一つの関数が呼ばれる
つまり メニュー表示時にValidationを行う事ができる

例えば、選択中のオブジェクトにScriptなりコンポーネントを自動で追加するメニュー拡張をしようと思った場合
GameObject以外を選択していたら 無効にすることができる

また、MenuItemの関数には、MenuCommandという引数を取る事が可能
調べたところ、このMenuCommandは Hierarchyの ルートが取れるようだ。まだ何に使うかわかってない。再調査が必要
Selection.activeObject で、現在選択中のオブジェクトが取得できる

ので、今回は下記のものを作る
Test/AddObject %b メニューを作り、選択しているものがGameObject以外は無効にする
GameObjectの場合は
MenuCommandという名前のGameObjectを MenuCommand.contextを親にして作成
NewGameという名前のGameObjectを Selection.activeObjectを親にし作成し RidgedBodyをつける
共にUndoに登録(これをしなければ Ctrl+Zで取り消せない)

    [MenuItem("Test/AddObject %b", true)]
    static bool AddObjectValidate()
    {
        // GameObjectか?
        return Selection.activeObject.GetType() == typeof(GameObject);
    }

    [MenuItem("Test/AddObject %b", false)]
    static void AddObject(MenuCommand command)
    {
        GameObject objMenuCommand = new GameObject("MenuCommand");
        // Undo登録
        Undo.RegisterCreatedObjectUndo(objMenuCommand, "Test_AddObject " + objMenuCommand.name);
        GameObjectUtility.SetParentAndAlign(objMenuCommand, command.context as GameObject);


        GameObject obj = new GameObject("NewGame");
        GameObjectUtility.SetParentAndAlign(obj, Selection.activeGameObject );

        // Undo登録
        Undo.RegisterCreatedObjectUndo(obj, "Test_AddObject " + obj.name);
        Undo.AddComponent<Rigidbody>(obj);

    }

f:id:murasame-labo:20171016053405p:plain

実行の結果、MenuCommandは Hierarchyルートに、NewGameは選択したGameObject(ここではTest)の下に出来た
なお GameObject以外を選択した場合には MenuがDisableする事も確認できた