Unityに関連する記事です

 デリゲート(Delegate)の実装方法について、活用事例を含めて紹介します。
今回は4回に渡り、ダイアログ(ポップアップ)内から外部クラスにある処理を制御する際に、デリゲートを利用した実装例を紹介します。

 この教材はクラス設計にも関わる内容になっており、自分で設計を考えて処理を実装していく方を対象としています。
そのため、プログラム中級者以上の、スキルアップを目指す方向けになっています。



はじめに


 具体的にどのような時にデリゲートを利用すると便利なのか、下図に示します。





 以上のように、クラス間の結合関係を疎結合に保つことで、仕様変更に対応しやすい設計で実装することが出来ます。

 デリゲートは応用パターンも多いため、この学習を通じて、自分のプロジェクトに合わせて改良していただくことを目的としています。


事前学習


 実装には UniRx を利用します。

 デリゲート、およびラムダ式による記述書式については、事前に理解しておく必要があります。
下記の教材を参考にしてください。

  => デリゲート
  => デリゲートとラムダ式の関係
  => デリゲートとラムダ式の活用事例


設計


 ダイアログ(ポップアップ)を制御する際にデリゲートを利用した実装例です。
最初に提示した図より引用します。





 具体的な実装内容としては、メソッドの引数にデリゲートを活用することで、
ダイアログ側では管理側との依存関係を持たず、管理側のメソッドを実行することが可能になります。


動画ファイルへのリンク



 ダイアログを制御する場合、多くはダイアログ自体の制御クラス(コントローラークラス)と、
ダイアログを開く処理を実行する管理クラス(マネージャークラス)の2つを利用する設計が多いと思います。

 その場合、【制御クラス ⇔ 管理クラス】の双方の依存関係が生じることが多くなり、疎結合が難しいことがあります。

 この状況を改善する方法の1つとしてデリゲートを採用する手法があります。

 【制御クラス ← 管理クラス】の一方向の関係性のみにすることで、
ダイアログの制御クラスは管理クラスのことを知らない(疎結合)状態を作り出すことが出来ます。



 設計のユースケースとして、管理クラスが制御クラスを実行してゲーム画面にダイアログを表示する際、
管理クラスの参照情報を制御クラスに渡すことで、ダイアログの制御クラスから管理クラスの処理を実行できる状態を作ることがあります。
これは【制御クラス ⇔ 管理クラス】の依存関係になります。

 このダイアログを開く処理の実行時にデリゲートを利用することで、管理クラスの参照情報ではなく、
ダイアログの制御クラスから実行したい、管理クラス内のメソッドの参照情報を渡すことで対処します。

 このメソッドの参照情報はデリゲートを利用することで保持することができ、
かつ、ダイアログの制御クラス側は、任意のタイミングで保持しているメソッドを実行することができます。

 この設計により、【制御クラス ← 管理クラス】の一方向の関係性が成り立ち、
制御クラス側は管理クラスと疎結合の状態を保ちつつ、管理クラス内のメソッドを実行することが可能になります。


ダイアログの作成


 Canvas 内に生成するためのダイアログを作成し、プレハブにしておきます。
作成するダイアログは任意です。

 ここではサンプルとして、各ゲームオブジェクトの画像を紹介します。














IDialogClose インターフェースの作成


 メソッドに戻り値を定義しておくことで、先々の処理に応用が出来るようになります。


<= クリックすると開きます



DialogBase クラスの作成

 
 DialogBaseクラスは、ダイアログの基本的な機能を提供する基底クラスです。

 IDialogClose インターフェースを実装しており、Hide()メソッドを提供してダイアログを非表示にします。

 UnityAction型のフィールド onCloseAction は、外部クラスの処理を保持するために使用されます。
ここに処理を保持しておくことで、任意のタイミングで処理を実行できます。

 また、直接的に外部クラスの参照を持たずに処理が実行できるため、依存関係がない(疎結合)状態が維持できています。


<= クリックすると開きます




 SetUpメソッドは、外部クラスから呼び出され、外部クラスの処理を引数として受け取ります。
これにより、依存関係を持たずに外部クラスの処理をダイアログ内で実行できます。

 Showメソッドは、ダイアログを表示するための基本的な処理を提供します。
表示前の準備や再設定が必要な場合、OnEnterOpenメソッドをオーバーライドして実装できます。

 Hideメソッドは、ダイアログを非表示にするための基本的な処理を提供します。
非表示にする前の処理が必要な場合、OnEnterCloseメソッドをオーバーライドして実装できます。

 OnExitCloseメソッドでは、ダイアログが非表示になった後に実行される処理を提供します。

 また、任意の処理内で UnityAction 内に保持している外部クラスの処理を呼び出す(実行する)ことができます。
今回の場合には、OnEnterClose() メソッドか、OnExitClose() メソッドにて処理を書いていますが、
これは、外部クラスの処理が、ダイアログを非表示にする際に実行したい処理であるためです。

 よって、外部クラスの処理がどういった処理なのかに合わせて、実行するタイミングを指定することで柔軟に対応が可能です。
これがデリゲートを活用した処理の大きなメリットになります。


DialogManager クラスの作成


 DialogManagerクラスは、ダイアログのテストと表示を担当するクラスです。

 Start メソッド内にデバッグ用の処理を記述し、ダイアログの生成(表示)を行っています。

 ダイアログ側に渡す処理もメソッド化し、それを引数として渡しています。
この部分はラムダ式を利用して匿名メソッドとして渡しても問題ありません。


<= クリックすると開きます




 Startメソッドでは、特定のキー(例:Aキー)が押されたときにダイアログを表示するための処理を設定しています。

 OpenDialogメソッドでは、ダイアログの生成と初期設定を行い、ダイアログを表示します。

 CloseDialogActionメソッドは、ダイアログが非表示になったときに呼び出されるコールバック処理です。
このメソッド内で、ダイアログが非表示になったことをログに記録しています。

 この処理のポイントは、private メソッドである CloseDialogAction() メソッドが、
外部クラスであるダイアログ側から処理されて実行できる部分です。

 デリゲートを活用することで、クラス間の依存関係を保持せずに、外部クラスから処理を実行することが出来ます。

 この処理がテスト処理に該当しますので、同じような形で、外部クラスにメソッドを提供することでコールバック処理に出来ます


解説


 ダイアログ側には DialogManager への依存関係がありません。
そのため、メンバ変数などを用意せずに済んでいます。

 代わりに UnityAction のデリゲートを用意し、ここに SetUp メソッドの引数として DialogManager クラスから渡ってきているメソッドの参照を保持します。

 このような設計にすることで、ダイアログ側は管理側である DialogManager クラスへの依存関係を持たずに、DialogManager 内にあるメソッドを実行する仕組みが構築できます。



 つまり、デリゲートの活用により、DialogBaseクラスとDialogManagerクラスは依存関係を持たずに連携できます
具体的には、SetUpメソッドを通じて、DialogManagerクラスから外部の処理(CloseDialogActionメソッド)をDialogBaseクラスに渡すことができます。

 これにより、DialogBaseクラス内でダイアログの表示や非表示に関連する処理を実行しつつ、必要なタイミングでCloseDialogActionメソッドを外部クラスから実行できます。

 また、DialogManagerクラスはダイアログのテストと表示を管理する役割を果たし、DialogBaseクラスはダイアログの基本的な機能を提供する役割を果たしており、
これらのクラス間の協力がデリゲートを通じて実現されています。


まとめ


 デリゲートを使用することにより、外部クラスとのコミュニケーションを効果的に実現し、クラス間の疎結合性を保持しています。

 また DialogBaseクラスはダイアログの基底となる処理になるため、
これを親クラスとして子クラスを作成することで、異なるダイアログに再利用可能です。
また外部クラスからカスタマイズできるため、汎用性が高いです。

 特に外部クラスの処理をデリゲートとして制御できるため、任意のタイミングで処理を実行できる部分もあり、実用性が高い設計になっています。



 以上でこの教材は終了です。

  => 次は デリゲートの実装例 です。
 

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます