バージョン4.6以降、Unity3DにはUI Systemが含まれ、 UIの作成プロセスが大幅に簡素化されています。 さらに、それはオープンソースプロジェクトです。 このシステムの中心には、 EventSystemとInputModulesという 2つの非常に重要なコンポーネントがあり、これらを使用してイベントを受信および処理できます。 本質的に、 InputModuleは通常のコンポーネントです。 これらはUIBehaviourの相続人であり、 UIBehaviourはMonoBehaviourを継承し、EventSystemからのイベントを処理するためのロジックを含んでいます。
イベントは、 ExecuteEvents.Execute()メソッドを呼び出すことにより、特定のGameObjectにディスパッチされます。 メソッド定義は次のとおりです。
public static bool Execute<T>(GameObject target, BaseEventData data, EventFunction<T> functor) where T : IEventSystemHandler;
このメソッドを呼び出すとき、 InpuModuleがTインターフェースまたはT継承インターフェースを実装する関連コンポーネントのリストのパラメーターとしてGameObjectへのリンクを渡す必要があります。 そのようなコンポーネントが複数ある場合、それらすべてが順番に呼び出されます。
ご覧のとおり、イベントを送信するには、ブロードキャストに適していないターゲットGameObjectへのリンクが必要です。
この問題の解決策は、ブロードキャストイベントを処理できるInputModuleがアタッチされたGameObjectsのリストを含むコレクションです。
public abstract class BroadcastInputModule<TEventType> : BaseInputModule where TEventType : IEventSystemHandler { protected override void Awake() { base.Awake(); BroadcastReceivers.RegisterBroadcastReceiver<TEventType>(gameObject); } protected override void OnDestroy() { base.OnDestroy(); BroadcastReceivers.UnregisterBroadcastReceiver<TEventType>(gameObject); } }
BroadcastInputModuleクラスは、ブロードキャストイベントハンドラーモジュールの基本クラスです。 その主なタスクは、このコレクションにモジュールを登録することです。
グローバルイベントに応答するモジュールの作成に移りましょう。このイベントを任意に「 SomethingHappened 」と呼びます。
[AddComponentMenu("Event/Something Happened Input Module")] public class SomethingHappenedInputModule : BroadcastInputModule<ISomethingHappenedEventHandler>, ISomethingHappenedEventHandler { public void OnSomethigHappened(SomethingHappenedEventData data) { Debug.Log("SomethingHappenedInputModule::OnSomethigHappened()"); } public override void Process() { } }
このコンポーネントは、 SomethingHappenedイベントの受信に関心があるすべてのGameObjectsに追加する必要があります。 ISomethingHappenedEventHandlerインターフェイスは次のとおりです。
public interface ISomethingHappenedEventHandler : IEventSystemHandler { void OnSomethigHappened(SomethingHappenedEventData data); }
ハンドラーのコレクションは、次のように非常に単純にすることができます。
public static class BroadcastReceivers { private static readonly IDictionary<Type, IList<GameObject>> BroadcstReceivers = new Dictionary<Type, IList<GameObject>>(); public static IList<GameObject> GetHandlersForEvent<TEventType>() where TEventType : IEventSystemHandler { if (!BroadcstReceivers.ContainsKey(typeof (TEventType))) { return null; } return BroadcstReceivers[typeof (TEventType)]; } public static void RegisterBroadcastReceiver<TEventType>(GameObject go) where TEventType : IEventSystemHandler { if (BroadcstReceivers.ContainsKey(typeof(TEventType))) { BroadcstReceivers[typeof(TEventType)].Add(go); } else { BroadcstReceivers.Add(typeof(TEventType), new List<GameObject>()); BroadcstReceivers[typeof(TEventType)].Add(go); } } public static void UnregisterBroadcastReceiver<TEventType>(GameObject go) { . . . } }
実際のゲームでは、おそらくこのコレクションにGameObjectsへの直接リンクではなくWeakReferencesを含める必要があります。これは既に要件に依存しています。
最後の要素はBroadcastExecuteEventsクラスです。
public static class BroadcastExecuteEvents { public static void Execute<T>(BaseEventData eventData, ExecuteEvents.EventFunction<T> functor) where T : IEventSystemHandler { var handlers = BroadcastReceivers.GetHandlersForEvent<T>(); if (handlers == null) return; foreach (var handler in handlers) { ExecuteEvents.Execute<T>(handler, eventData, functor); } } }
定義からわかるように、これはExecuteEventsの単なるラッパーであり 、1つのタスクのみを実行します。指定されたイベントに適切なハンドラーを選択して呼び出します。
これで、次のようにイベントをブロードキャストできます。
BroadcastExecuteEvents.Execute<ISomethingHappenedEventHandler>(null, (i, d) => i.OnSomethigHappened(new SomethingHappenedEventData()));
この記事のソースコードは、 github.com / rumyancevpavel / BroadcastMessagingから取得できます。