Help us understand the problem. What is going on with this article?

「MonKey - Productivity Commands」のカスタムコマンドでさらにUnity上の作業を効率化する

PONOS Advent Calendar 2019の5日目の記事です。

昨日は@nimitsuさんのGameLift RealTimeServerで遊んでみよう for Unity(AWS設定編)でした。

はじめに

本記事はPONOS Advent Calendar 2019の2日目の記事である「MonKey - Productivity Commands」のコマンド操作でUnity開発を効率化するの続編となります。
assetstore.png
MonKey - Productivity Commands - Asset Store

前回はMonKeyを使用してどんな事ができるのか、導入について書かせてもらいました。
今回は少し発展して、カスタムコマンドの作り方についてまとめたいと思います。

MonKeyには予め130超もの豊富なコマンドが用意されており、様々な処理をコマンドから実行できますが、それらのコマンドだけではそのプロジェクト特有の処理まではサポートできません。
カスタムコマンドを利用することにより、プロジェクト独自の処理についてもコマンド化し操作時間を短縮することができるので、MonKeyを有効利用したいと思っている方は参考にしてみてください。

なお、

  • Unity 2019.2.12f1
  • MacOS 10.14.6

の環境で動作確認しています。

カスタムコマンド

MonKey.Command属性をstaticメソッドに付与することで、そのメソッドをコマンド化することができます。
なお、スクリプトはEditorフォルダ以下に存在している必要がありますのでご注意ください。

using MonKey;

public static class SampleCommands
{
    [Command("Sample Command 01")] // 引数にMonKey上のコマンド名を指定する
    static void SampleCommand01()
    {
        Debug.Log($"コマンド\"SampleCommand01\"を実行したログです。");
    }
}

SampleCommand01.png
MonKeyのコマンドパレット上に表示されました!
image.png
コマンドを実行すると、メソッド内に記述した処理が実行されています。
このように、メソッドをMonKeyのコマンド化するのは非常に簡単です。

使用例:選択中のGameObjectの階層パスをコンソールに出力する

さて、ここからはより実用的なカスタムコマンドを作成してみます。
今回作成するのは「選択中のGameObjectの階層パスをコンソールに出力する」コマンドです。
Example.png
例えば、上のようなHierarchyで実行した場合には「Parent/SecondSon/Grandchild/Great-grandson」とコンソールにログ出力する挙動となります。

『SecondSon』の下にある『Grand-grandson』のことを他の人に伝えたいとき、Hierarchyの階層のパスを提示できれば、『EldestSon』の下にいるGrand-grandsonを誤って参照しまうことを防止できます。

コマンドの基本情報を設定する

前項で作成したSample Command 01ですが、他のコマンドと異なり「ヘルプ」や「短縮されたコマンド名」が表示されておらず、実際に使うには不便でした。
今回はそれらコマンドに関する基本情報をちゃんと設定してみましょう。

MonKey.Command属性には上記の「ヘルプ」や「短縮されたコマンド名」のようなコマンドの基本情報を設定するためのプロパティが用意されています。

MonKey.Command属性のプロパティ(抜粋)

プロパティ 用途
Name コマンド名。コマンドの検索に用いられる。
QuickName 短縮されたコマンド名。
3文字以内に収めることを推奨されている。
Help コマンド名の下に表示されるヘルプ。
1行より長くなるとフォーマットが完全ではない可能性がある。

実際にこれらのプロパティを使用して「ヘルプ」と「短縮されたコマンド名」が設定されたSample Command 02を作成します。

[Command(
    "Sample Command 02",
    QuickName = "SC2",
    Help = "選択中のGameObjectの階層パスをコンソールに出力する"
)]
static void SampleCommand02()
{
}

SampleCommand02_01.png
設定した「ヘルプ」と「短縮されたコマンド名」がコマンドパレット上に表示されていることがわかります。
また、短縮されたコマンド名である「sc2」を入力しただけでSmaple Command 02が候補として表示されます。

コマンドから選択されているGameObjectを参照する

次に、実際に選択中のGameObjectを参照してコンソールに出力する、というコマンドの処理部分を実装してみましょう。
現在選択されているGameObjectを参照するためには、通常エディタ拡張で使用しているUnityEditor.Selectionではなく、MonKeyから提供されているMonKey.Editor.MonkeyEditorUtils.OrderedSelectedGameObjectsを使用します。

(なお、選択されたGameObjectではなく、選択されたTransformを取得することのできるMonKey.Editor.MonkeyEditorUtils.OrderedSelectedTransformも用意されています)

IEnumerable<GameObject>で返ってくるので、foreachで列挙し処理していきます。

選択中のGameObjectを取得し、そのパスを出力するコードは以下になります。

using MonKey.Editor;

...

// OrderedSelectedGameObjectsから選択中のGameObjectを列挙できる。
foreach (var selectedGameObject in MonkeyEditorUtils.OrderedSelectedGameObjects)
{
    // 親のGameObjectの名前を手前に連結していく。
    var pathBuilder = new System.Text.StringBuilder(selectedGameObject.name);
    var parent = selectedGameObject.transform.parent;
    while (parent != null)
    {
        pathBuilder.Insert(0, parent.name + "/");
        parent = parent.transform.parent;
    }

    Debug.Log(pathBuilder.ToString());
}

SampleCommand02_02.png
この選択状態でコマンドを実行すると、
SampleCommand02_03.png
このように、各GameObjectの階層をパスとして出力することができました。

コマンドを実行できる条件を設定する

現在のSample Command 02は、GameObjectを全く選択していなくてもコマンドを実行することができます。

選択していない状態で実行したとしてもMonkeyEditorUtils.OrderedSelectedGameObjectsの要素が0で返ってくるだけなのでエラーが発生することはありませんが、それではコマンドを実行する意味がないため、「GameObjectを選択している状態でのみ」実行できるように、検証条件を設定してみましょう。

コマンドの検証条件はMonKey.Command属性のDefaultValidationプロパティで設定します。
DefaultValidationにはMonKey.DefaultValidation列挙体の値が使用できます。

MonKey.DefaultValidation列挙体(抜粋)

用途
AT_LEAST_ONE_GAME_OBJECT 1個以上のGameObjectを選択している。
AT_LEAST_TWO_GAME_OBJECTS 2個以上のGameObjectを選択している。
IN_PLAY_MODE プレイモード中である。
IN_EDIT_MODE プレイモード中ではない。

今回は、「GameObjectを選択している状態でのみ」実行できるようにしたいので、MonKey.DefaultValidation.AT_LEAST_ONE_GAME_OBJECTを指定します。

[Command(
    "Sample Command 02",
    QuickName = "SC2",
    Help = "選択中のGameObjectの階層パスをコンソールに出力する",
    DefaultValidation = DefaultValidation.AT_LEAST_ONE_GAME_OBJECT
)]
static void SampleCommand02()
{

SampleCommand02_04.png
GameObjectを選択していない状態でコマンドを選択すると…
SampleCommand02_05.png
ご覧のように「Select at least one GameObject」の警告が表示され、コマンドを実行することができません。

コマンドの製作者が自身だけで使用する分には使い方を気をつければいいので、検証条件の定義は必須ではありませんが、他者へ共有する予定がある場合は検証条件を正しく定義して正しい状況で使用してもらえるようにしたいですね。

おわりに

カスタムコマンドを作成してMonKeyが実行できる機能を充実させることで、Unity上の作業を更に効率化することができます。

なお、Unityエディタ上からstaticメソッドを実行するにはUnityEditor.MenuItem属性でメニューアイテム化する、という方法もありますが、MonKeyなら処理の実行条件の検証を行ったり実行時に引数を与えることができるので、メニューアイテムとして実行するよりも柔軟な処理の実行が可能となります。
そういった用途で実行したい処理がある場合にはMonKeyのカスタムコマンド作成を検討してみてください。

さて、PONOS Advent Calendar 2019は6日目も続けて私@e73ryoが担当する予定です。
次回は引数を与えてカスタムコマンドを実行する方法について紹介したいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした