[Unity]:PlayMaker カスタムアクション入門

PlayMakerではアクションという処理の単位を組合せて、処理を記述していきます。

PlayMaker公式アクションリファレンス(英語)

標準でもかなりの数のアクションが用意されていますが、実際にPlayMakerを使って作業していると標準のものでは処理を実現できそうもない場合が出てきます。
その場合はカスタムアクションを自分で作成して、標準のアクションと同様にPlayMakerで使用することができます。

ここではPlayMaker標準で用意されている「IntOperator」アクションを例にとり、アクションの記述の仕方を解説していきます。
「IntOperator」は2つのInt値と計算方法を指定し、その結果を指定のInt型変数に代入するアクションです。

namespace HutongGames.PlayMaker.Actions
{
	・・・
}

独自のネームスペースを使うことも可能ですが、特に理由が無い限りはHutongGames.PlayMaker.Actionsを使用するのが無難です。

namespace HutongGames.PlayMaker.Actions
{
	[ActionCategory(ActionCategory.Math)]
	[Tooltip("Performs math operation on 2 Integers: Add, Subtract, Multiply, Divide, Min, Max.")]
	public class IntOperator : FsmStateAction
	{
		・・・
	}
}

PlayMakerのアクションブラウザに表示される時のカテゴリを指定します。

PlayMakerActionBrowser

標準のカテゴリに追加することもできますし、独自のカテゴリに追加することもできます。
独自のカテゴリに追加したい場合は以下のようにカテゴリ名を文字列で指定します。

	[ActionCategory("CustomCategory")]
namespace HutongGames.PlayMaker.Actions
{
	[ActionCategory(ActionCategory.Math)]
	[Tooltip("Performs math operation on 2 Integers: Add, Subtract, Multiply, Divide, Min, Max.")]
	public class IntOperator : FsmStateAction
	{
		・・・
	}
}

アクションブラウザに表示するアクションの説明文を指定します。

PlayMakerActionBrowserPreview

省略しても構いません。

namespace HutongGames.PlayMaker.Actions
{
	[ActionCategory(ActionCategory.Math)]
	[Tooltip("Performs math operation on 2 Integers: Add, Subtract, Multiply, Divide, Min, Max.")]
	public class IntOperator : FsmStateAction
	{
		・・・
	}
}

HutongGames.PlayMaker.FsmStateActionを継承させます。

		[RequiredField]
		public FsmInt integer1;
		[RequiredField]
		public FsmInt integer2;
		public Operation operation = Operation.Add;
		[RequiredField]
		[UIHint(UIHint.Variable)]
		public FsmInt storeResult;
		public bool everyFrame;

PlayMakerIntOperator

PlayMakerエディタ上に表示されるパラメータとなります。
「RequiredField」属性を指定すると省略不可となり、エディタ上で適切な値を指定しない場合にエラーとなります。

「UIHint」属性を指定することで、エディタ上での表示の仕方を変えることができます。
「UIHint.Variable」を指定した場合には、FSMで用意した変数から選択することしかできなくなります。

メンバ変数の型を「Fsm〜」という型で指定することにより、エディタの機能を利用した便利な指定ができるようになります。
ここではFsmIntしか登場しませんが、他にFsmFloatやFsmStringなど様々な型が用意されています。

また、通情のC#の型も使用することができます。ここでは「everyFrame」がbool型で宣言されています。

		public override void Reset()
		{
			integer1 = null;
			integer2 = null;
			operation = Operation.Add;
			storeResult = null;
			everyFrame = false;
		}

新規にアクションを追加した場合の初期値、またはエディタ上でリセットをかけた場合にセットされる値を指定します。

		public override void OnEnter()
		{
			DoIntOperator();
			
			if (!everyFrame)
				Finish();
		}

アクションが実行される時に呼び出されます。
この中に直接処理を記述しても構いませんが、ここでは実際の処理は「DoIntOperator()」の中に記述されています。
処理の終了には必ず「Finish()」を呼び出す必要があります。
ただし、ここでは毎フレームの処理を行う場合は処理を終了させたく無いのでeneryFameフラグにより条件分岐されています。

		// NOTE: very frame rate dependent!
		public override void OnUpdate()
		{
			DoIntOperator();
		}

毎フレーム実行される処理を記述します。

		void DoIntOperator()
		{
			int v1 = integer1.Value;
			int v2 = integer2.Value;

			switch (operation)
			{
				case Operation.Add:
					storeResult.Value = v1 + v2;
					break;

				case Operation.Subtract:
					storeResult.Value = v1 - v2;
					break;

				case Operation.Multiply:
					storeResult.Value = v1 * v2;
					break;

				case Operation.Divide:
					storeResult.Value = v1 / v2;
					break;

				case Operation.Min:
					storeResult.Value = Mathf.Min(v1, v2);
					break;

				case Operation.Max:
					storeResult.Value = Mathf.Max(v1, v2);
					break;
			}
		}

「Fsm〜」型の変数はValueプロパティにより実際の値にアクセスすることができます。
注意点としてはin/outの区別が無いので、処理を記述する際に余計な値を変更してしまわないようにしましょう。

ーーーーー
以上のようにカスタムアクションはとても簡単に作成することができます。
GameObjectの参照をとったり、より複雑な処理をする場合は、標準のアクションの中から似たような処理をするものを見つけ、そのスクリプトを参考にすると良いでしょう。
アクションブラウザ上でアクションの右クリックメニューから簡単にスクリプトを参照することができます。