UnityでDispatcherで通知してみる(Event System - Dispatcher)

Dispatcherの仕組みを作ろうとしたら前にLevel11で無料だったアセットがあったのでこれの使い方把握も兼ねた実験。

<a href="https://www.assetstore.unity3d.com/jp/#!/content/12715" target="_blank">Event System - Dispatcher</a>

##インポートしたところ
<img width="200" alt="スクリーンショット 2016-09-11 14.12.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/a03b6584-362e-f8c0-6312-6985aeb84736.png">

##こんな感じのシンプルなものを作りました。
オブジェクトは

- エリア(森)
- あゆめぐ(あゆめぐリーダー(１匹)と　あゆめぐがいます)
- 動物(猫とウサギ)

###簡単な機能説明
天候変化は全てのオブジェクトが受け取ります
あゆめぐに通知はあゆめぐ全体に
動物には動物全体に
エリアに通知はエリア全体に
メッセージ削除は全てのオブジェクトが受け取ります
かえるのーはあゆめぐリーダーがまず受け取り、2秒後に仲間にさらにメッセージを通知します。

<img src="http://ayumegu.daa.jp/img/Qiita/Project5.gif" width="700px">

使ってみた感じ、メッセージを継承してカスタマイズしたものを送ることもできるし、遅延にも対応しているし便利＾＾
１から作らず済んじゃったわーい。

ソースはやっつけだけどこんな感じ

これがボタンと現在の天気持ってるクラス

```csharp
using UnityEngine;
using System.Collections;
using com.ootii.Messages;

public class EventDispatcherMain : MonoBehaviour {

	public enum Weather
	{
		SUNNY,
		RAINY,
	}

	private Weather weather;

	void Awake()
	{
		weather = Weather.SUNNY;
	}

	public void WeatherChangeCick()
	{
		string message = "";
		if(weather == Weather.SUNNY)
		{
			weather = Weather.RAINY;
			message = "雨だー";
		}
		else
		{
			weather = Weather.SUNNY;
			message = "いい天気だー";
		}

		Message lMessage = new Message();
		lMessage.Type = "EVERYONE";
		lMessage.Sender = this;
		lMessage.Data = message;
		lMessage.Delay = EnumMessageDelay.IMMEDIATE;
		MessageDispatcher.SendMessage(lMessage);
	}

	public void AyumeguMessageClick()
	{
		MessageDispatcher.SendMessage(this, "Ayumegu", "なにしようかな〜", 1f);
	}

	public void AnimalMessageClick()
	{
		MessageDispatcher.SendMessage(this, "Animal", "こんにちは", 0);
	}

	public void FieldMessageClick()
	{
		MessageDispatcher.SendMessage(this, "Field", "あ〜〜", 3f);
	}

	public void DeleteMessageClick()
	{
		MessageDispatcher.SendMessage("DeleteMessage", 0);
	}

	public void LeaderAyumeguMessageClick()
	{
		MessageDispatcher.SendMessage(gameObject, "AyumeguLeader", "TARGET", "みんな帰るぞー", EnumMessageDelay.IMMEDIATE);
	}
}

```

各イベントを受け取るクラスはAyumegu Animal Fieldと作成したものを各オブジェクトにアタッチしていますが
どれもシンプルなのでその中でも一番分岐があるAyumeguのソースだけ。
リーダーだけ、部下だけというフィルタが入っているだけだけど。

```csharp

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using com.ootii.Messages;

public class Ayumegu : MonoBehaviour {

	public Text messageText;

	void Start () {
		messageText = transform.FindChild("MessageText").GetComponent<Text>();
		MessageDispatcher.AddListener("EVERYONE", OnMessageReceived);
		MessageDispatcher.AddListener("Ayumegu", OnMessageReceived);
		MessageDispatcher.AddListener("DeleteMessage", OnDeleteMessageReceived);
		MessageDispatcher.AddListener("TARGET", OnTargetMessageReceived);
	}

	public void OnMessageReceived(IMessage rMessage)
	{
		string str = rMessage.Data as string;
		messageText.text =  str;
		rMessage.IsHandled = true;
	}

	public void OnDeleteMessageReceived(IMessage rMessage)
	{
		messageText.text =  "";
		rMessage.IsHandled = true;
	}

	public void OnTargetMessageReceived(IMessage rMessage)
	{
		string recipient = rMessage.Recipient as string;
		// リーダーへのメッセージはリーダーのみ受け取る
		if(recipient == "AyumeguLeader" && gameObject.name == "AyumeguLeader")
		{
			string str = rMessage.Data as string;
			messageText.text =  str;
			rMessage.IsHandled = true;

			// 部下に2秒後撤退を伝える
			MessageDispatcher.SendMessage(gameObject, "Ayumegu", "TARGET", "おーー!", 2f);
		}

		// 部下へのメッセージは部下のみが受け取る
		if(recipient == "Ayumegu" && gameObject.name == "Ayumegu")
		{
			string str = rMessage.Data as string;
			messageText.text =  str;
			rMessage.IsHandled = true;
		}
	}
}
```

MessageDispatcher.SendMessageのメソッドが引数のパターンが沢山あります。
またIMessageはカスタムしたオリジナルのクラスを作ることも可能でその場合はMessage.csを継承して作る。

あとはEnumMessageDelayが時間指定なのですが定数で
EnumMessageDelay.IMMEDIATE //即時 0
EnumMessageDelay.NEXT_UPDATE //次のUpdate -1
EnumMessageDelay.ONE_SECOND // １秒後
とあり、地味に次のUpdateというのが対応しているのが素敵だなと思った。

はい、これはここまで。