‫わかりました｡
‫そこで､ この講義では､ マルチキャスト､ デリゲート､ イベントについて学びます｡
‫そこで､ まず問題を探ってみましょう｡
‫ゲームをゼロから開発することを想像してください｡
‫私たちのコードは､ グラフィックスとオーディオのライブラリと､ プレーヤーのロジックを組み合わせたものです｡
‫では､ 早速コーディングしてみましょう｡
‫次のような簡単なクラスを考えてみましょう｡
‫まず最初に､ このレンダリングクラスがあります｡ ゲームの開始時にレンダリングエンジンを有効にして､ ビジュアルの描画を開始するようにします｡
‫レンダリングして､ ビジュアルの描画を開始するわけです｡
‫また､ ゲーム終了時には､ レンダリングエンジンを停止させたいと考えています｡
‫そこで､ ゲームオーバーのメソッドを用意し､ レンダリングエンジンを停止させることにしました｡
‫そこで､ ここではコンソールライトラインステートメントを使っているだけです｡
‫もちろん､ これはもっと複雑なコードになるし､ 実際に何かをすることになる｡
‫私たちの場合は､ イベントだけでなく､ マルチキャストデリゲートの概念も理解しようとしているところです｡
‫そのため､ コンソールに赤線のステートメントで表示するだけなのです｡
‫これがレンダリングクラスです｡
‫では､ オーディオシステムのクラスを見てみましょう｡
‫そこで､ このオーディオシステムには､ オーディオシステムを起動し､ 音声を再生するダーツゲーム方式も用意されています｡
‫そして､ 基本的にオーディオを停止させるゲームオーバー方式を採用しています｡
‫そして最後にプレーヤーがあり､ プレーヤーにはプレーヤー名があります｡ この単純なコンストラクタでは､
‫作成されたオブジェクトに渡された名前に基づいて､ その名前を設定するだけです｡
‫また､ ここではゲームオーバーの方法だけでなく､ ゲームの開始も用意されています｡
‫これはIDを持つプレーヤーを生成するもので､ これはプレーヤー名として割り当てた特定のIDを持つプレーヤーを削除するものです｡
‫以上､ 3つのクラスを紹介しましたが､ ここでは比較的シンプルに説明します｡
‫それでは､ mainメソッドに移動してみましょう｡
‫そこで､ メイン・メソッドの内部で､ これらのシステムのオブジェクトを作成することにします｡
‫まず､ オーディオシステム､ そしてレンダリングエンジンです｡
‫そして､ IDを持つ選手も2人作ります｡
‫プレイヤー1はCAO､ プレイヤー2はデシルバということになりますね｡
‫そこで､ それぞれのクラスからstart gameメソッドを呼び出すことで､ レンダリングエンジン､ オーディオシステム､ プレイヤーのスポーンを開始する必要があります｡
‫だから､ そうしよう｡
‫そして､ このようにするつもりです｡
‫だから､ オーディオシステム､ ゲームレンダリングエンジンを開始するゲームプレーヤー1とゲームを開始するプレーヤーそれぞれを開始しない､
‫と言うことです｡
‫そして､ ゲームは進行中です､ 何かキーを押してゲームを終了してくださいというだけです｡
‫そこで､ 今やりたいことは､ プレイヤーがボタンを押したら､ 基本的にゲームを終了させることです｡
‫だから､ もちろんもっと複雑なものになる｡
‫例えば､ プレイヤーがオプションメニューですべてのフォーまたはを押したとします｡
‫彼がゲームを閉じると､ 次のコードが実行されるのです｡
‫次のコードでは､ オーディオシステムのゲームオーバー､ レンダリングエンジンのゲームオーバーメソッド､ プレイヤー1､
‫プレイヤー2のゲームオーバーメソッドを呼び出すことになります｡
‫だから､ それを大切にしよう｡
‫ここにも書き加えよう｡
‫ちなみに､ そうしないと直接シャットダウンされてしまうので､ リードステートメントが必要です｡
‫そこで､ 手動でキーを押してすべてをシャットダウンし､ 基本的にゲームオーバーになるように､ ここに読み取りステートメントを追加してみます｡
‫では､ 実際にこれを実行して､ 何が起こるか見てみましょう｡
‫オーディオシステムが起動し､ オーディオが再生され､ レンダリングエンジンが起動し､ ビジュアルが表示され､ そしてプレイヤーがスポーンされるわけです｡
‫つまり､ プレイヤー1とプレイヤー2が生まれるわけです｡
‫これでゲームが動いて､ 遊べるようになりました｡
‫そして､ 完成させたいと思ったら､ キーを押すのです｡
‫そこで､ あるキーを押してみる｡
‫そして､ レンダリングエンジンが止まり､ オーディオシステムが止まり､ 両方のプレーヤーを取り除いたのがお分かりいただけると思います｡
‫そのため､ この設定にはかなりの苦労があったようです｡
‫今､ 私たちはもっとたくさんのものでこれをやらなければならないと想像していますが､ うまくいかないことがいくつかあるかもしれませんね？
‫そのため､ システムを増やすとなると､ ゲーム開始やゲームオーバーのメソッドを呼び出すのを忘れてしまうなど､
‫かなり複雑になってしまいます｡
‫さらに悪いことに､ これらのメソッドの1つを2回呼び出すと､ さまざまな問題が発生し､ 多くの保護コードを配置しなければならなくなります｡
‫ですから､ この物体が生きているのかどうか､ 本当に確かめなければならないのです｡
‫このメソッドを呼び出したのか､ このメソッドを呼び出したことがあるのか､ などなど､ 複雑すぎる｡
‫そして､ ここで役に立つのがマルチキャストデリゲートです｡
‫マルチキャストデリゲートは､ 複数のメソッドへの参照を格納できるリストとして機能するデリゲートで､
‫基本的にはそれだけです｡
‫さて､ これはかなり複雑に聞こえますが､ 構築してみると､ おそらくもっと理解できるようになるでしょう｡
‫そこで､ Game Event Managerという静的なクラスを作成しましょう｡
‫だから
‫わかりました｡
‫では､ 新規に作成してみましょう｡
‫クラスはこちら
‫そして､ これをゲームイベントマネージャーと呼ぶことにします｡
‫わかりました｡
‫つまり､ このゲームイベントマネージャーは､ デリゲートを持つことになります｡
‫そこで､ Game Eventというデリゲートを新規に作成することにします｡
‫これは何も返しませんが､ デリゲートタイプで､ このクラスの外でも使えるようにパブリックになっています｡
‫デリゲートがどのように機能するかを見てきましたが､ このデリゲートを使って､ 基本的に1つ以上のイベントを追加できるようにしましょう｡
‫それでは､ on game startとon game endという2つの変数を作りましょう､ これらはgame eventという型になります｡
‫だから､ 我々の代表のタイプから外れることになる｡
‫つまり､ これがゲームイベントのデリゲートになり､ これがゲームイベントのデリゲートになるわけです｡
‫このように､ 2つのデリゲート変数を使用することができます｡
‫では､ 3つのクラスに話を戻しましょう｡
‫ゲーム開始時とゲーム終了時のデリゲートに､ ゲーム開始とゲーム終了のメソッドを追加してみましょう｡
‫また､ これらのメソッドは公開する必要はありません｡
‫なぜなら､ イベントを追加したり購読したりするためにオーディオシステムのコンストラクタを使用するため､
‫メソッドを公開する必要がないからです｡
‫そこで､ ゲーム・マネージャーのデリゲートにメソッドを追加するのに最適な場所は､ コンストラクタの中です｡
‫それが､ ここでの活動です｡
‫そして､ オブジェクトが生成されると､ そのオブジェクトのメソッドが自動的にデリゲートに追加される､
‫つまりサブスクライブされることになる｡
‫つまり､ ゲーム開始とゲームオーバーのメソッドが､ ゲーム開始のデリゲートでゲームイベントマネージャーに追加されるわけです｡
‫そして､ ここでプラスの等号を使って､ このメソッドをマルチキャストデリゲートに追加したいと言っているのです｡
‫つまり､ 基本的に私たちはこのイベントを購読し､ そのイベントが発生するのを待っているのです｡ なぜなら､ そのイベントが発生すると､
‫私たちのメソッドが呼び出されるからです｡
‫つまり､ レンダリングエンジンのクラスとプレイヤーのクラスで､ 同じことができるようになったのです｡
‫ここで重要なのは､ 単なる等号ではなく､ プラスの等号を使っていることで､ 代入していないわけです｡
‫そして､ 署名が何を意味するのか､ それが私たちにとってどうなるのか､ 後で確認することになります｡
‫しかし､ ここでは､ もう一つを追加するだけです｡
‫イベントコレクター､ いわばイベント担当者へのメソッド｡
‫つまり､ 実行すべきイベントやメソッドをすべて収集しているのです｡
‫つまり､ マルチキャストのデリゲートですね｡
‫では､ 同じことをレンダリングエンジンでやってみましょう｡
‫自分でやってほしい｡
‫そこで､ ビデオを一時停止して､ このオーディオシステムで行ったのと同じコードを割り当てたり､ 同じコードを構築してみたりしてください｡
‫だからまず､ もうメソッドを公開する必要がないので､ メソッドをプライベートなものにするようにしたんだ｡
‫その必要がないため､ このクラス以外では決して呼び出すことはありません｡
‫そのため､ 常に非公開にするのが良い方法です｡
‫しかし､ 呼び出せるのはコンストラクタですよね？
‫そこで､ レンダリングエンジンのオブジェクトをパブリックに作成することができます｡
‫これで､ ゲームイベント・マネージャのゲーム開始時に､ ゲーム開始メソッドを追加することができます｡
‫また､ ゲームオーバーも同様です｡
‫そこで､ ここではプラスイコールも使っています｡
‫つまり､ ゲーム開始時とゲームオーバー時のイベントを購読していると言うことです｡
‫つまり､ 基本的にはゲーム開始時のイベントが一度だけ発生すると言っているわけです｡
‫ゲーム開始メソッドとも呼ばれます｡
‫お願いします｡
‫私たちのというのは､ レンダリングエンジンのゲーム開始方法のことです｡
‫そこで､ このメソッドを呼び出すことになります｡
‫そしてもちろん､ ゲームオーバーになれば､ ゲームオーバーメソッドはこちらのメソッドを呼び出すことになります｡
‫そういうアプローチで使っているわけです｡
‫では､ 少しチャレンジしてみましょう｡
‫同じことをプレイヤークラスでやってください｡
‫なるほど｡
‫ではまず､ 合格を祈ります｡
‫そしてまあ､ ゲーム開始とゲームオーバーのメソッドを外部から呼び出すことはできないはずなので､
‫この2つのメソッドをprivateにすることも確認するつもりです｡
‫しかし､ ここにはすでにコンストラクタがあるので､ このコンストラクタを使用して､ ゲーム開始時とゲーム終了時のメソッドをゲーム開始イベントとゲーム終了イベントにサブスクライブすることにします｡
‫そこで､ 今度はゲームイベントマネージャーで｡
‫mainメソッドからイベントを発生させるために､ 2つのpublic staticメソッドを追加しましょう｡
‫では､ ここでできること｡
‫レンダリングエンジン､ オーディオシステム､ プレーヤーがすべて作成された後､
‫このイベントがトリガーされると､ 何かが実行されるからです｡
‫しかし､ そうなった場合にどうすべきかは､ 特に言っていません｡
‫だから､ そのイベントが発生するのであれば
‫そこで､ ゲーム開始時に起動するスタティックメソッドを作ってみましょう｡
‫つまり､ レンダリングエンジンを作成したら､ 他のメソッドがすでにこのイベントを受信していることになります｡
‫そして､ 例えばここにあるコードが実行されたり､ オーディオシステムが作成されてこのコードが実行されたり､ プレーヤーが作成されてこのコードが実行されたりすると､
‫ここにあるこのステートメントが真になるのです｡
‫そのため､ ゲーム開始時のゲームイベントは空ではない､ つまりnullにはならない｡
‫そして､ ここにあるコードが実行されます｡
‫つまり､ ゲームが開始されたと表示し､ ゲーム開始を呼び出すということです｡
‫このイベントに登録されたすべてのメソッドが起動します｡
‫つまり､ ここでこのメソッドを呼び出すと､ このゲームイベントは､ いわば､
‫ここでこのメソッドが実行されるわけです｡
‫このメソッドが実行されるのと同様に､ このメソッドも少し見ていきます｡
‫それがトリガーゲインスタートなんですね｡
‫だから､ こうやってトリガーするんです｡
‫このメソッドを呼び出すだけで､ ゲームイベントそのものと同じように静的な状態にすることができます｡
‫だから､ 私たちはそれを実現したいし､ そのためにこの静止画を作っているのです｡
‫ですから､ これらのメソッドを呼び出すためにオブジェクトを作成する必要はありません｡ そして､ 自分のゲームオーバーのために､
‫もうひとつ静的メソッドを作成しましょう｡
‫そして､ ビデオを一時停止して､ 今の自分を本当に早く作り上げてみることをお勧めします｡
‫なるほど｡
‫だから､ 合格してほしい｡
‫基本的にはここでやったことと同じなのですが､ 今度はこっちのエンドゲームでやることになるんです｡
‫そこで､ この public static void triggered game over メソッドでイベントをトリガーし､ game over が null でない場合は､ このメソッドを使用するようにしました｡
‫つまり､ このコードが実行され､ ゲームオーバー時に実行され､
‫ゲームオーバーメソッド､ またはこのゲームオーバーイベントに割り当てられた､
‫またはサブスクライブしたすべてのメソッドが呼び出されます｡
‫つまり､ 新しいエンジンを作るとしたら､ レンダリングエンジンとオーディオエンジンがあるわけです｡
‫3つ目のエンジンを作ったとすると､ もうこのようなものを手動で呼び出す必要はありません｡
‫しかし､ エンジンの中で直接､ そのイベントを購読するように設定することができ､ そのイベントが発生すると自動的にメソッドが呼び出されます｡
‫わかりました｡
‫それでは､ mainメソッドのコードを見てみましょう｡
‫もちろん､ これらのゲーム開始メソッドは､ 以前は公開されていましたが､
‫今はもう公開されていませんから｡
‫だから､ 今はそうなっている｡
‫なるようになる｡
‫まあ､ 私立だから閉鎖的なんだろうけど｡
‫では､ 実際にこのゲームイベントをトリガーすることを確認しましょう｡
‫ここでゲームイベントマネージャーを用意し､ ゲーム開始のトリガーを設定しました｡
‫ですから､ すべてのプレーヤーとすべてのシステム､ そしてすべての準備が整えば､ 実行に移せるのです｡
‫そして今度は､ この下にあるゲームオーバーの方法で､ 同じことができるのです｡
‫では､ ここでゲームオーバーのイベントを発生させましょう｡
‫つまり､ よりシンプルでクリーンなコードを作ることができるようになるのです｡
‫つまり､ 私たちのコードが完璧に動作することを保証してくれるのです｡
‫では次に､ そこにもう一人プレイヤーを追加するとしよう｡
‫考えて､ これらのメソッドをすべて呼び出す必要はないのです｡
‫そうですね､ ゲーム開始メソッドと呼ばれるもの､ ゲームオーバーメソッドと呼ばれるもの､ などです｡
‫この新しいプレーヤーを作成すれば､ それに応じて自動的にメソッドを呼び出すことができます｡
‫オーディオシステムの起動､ オーディオレンダリング､ エンジン描画､ ビジュアル､
‫そしてトグルシルバーとドラゴンドックと呼ばれるプレイヤーのスポーニングが開始されました｡
‫では､ 次にボタンを押してみましょう｡
‫そして､ ゲームが終わったのを確認することができました｡
‫オーディオシステムが停止した｡
‫レンダリングエンジンが停止したため､ すべてのプレーヤーを削除します｡
‫これがマルチキャストデリゲートの本当の実力なんですね｡
‫超､ 超便利､ 超強力｡
‫3番目のオブジェクトであるプレイヤーは､ ゲーム開始時とゲーム終了時の両方のイベントが発生したときにオブジェクトが通知されるため､
‫自動的にゲーム開始とゲーム終了のメソッドが呼び出されたことがわかります｡
‫さて､ デリゲートを使う場合､ うまくいかないこともあります｡
‫まずは､ 修正に何時間もかかるようなミスをいくつか見てみましょう｡
‫例えば､ 誤って､ プラス等号を使用してイベントにメソッドをサブスクライブする代わりに､ プラス等号を使用せずに､
‫例えば､ プレーヤーのクラスに移動したとしましょう｡
‫偶然にも､ 等号を使っただけだったでしょう｡
‫だから､ コンパイラは､ これは間違っていないのだから､ これは間違っているとは言わない｡
‫また､ メソッド一つで既存のイベントを上書きすることも可能です｡
‫つまり､ ここでやっていることは､ この時点で購読されていたものが何であれ､ それを上書きする､
‫ということです｡
‫それが､ まあ､ 基本的にはここで起こることなんです｡
‫そこで､ ゲーム開始時とゲームオーバー時に参照されるメソッドをすべて削除し､ プレイヤー（正確には最後に作成されたプレイヤー・オブジェクト）を､
‫これらのイベントに対する唯一のサブスクライブとして設定します｡
‫また､ ゲームスタート時とゲームオーバー時は実際に公開されているので､ どこからでも直接呼び出すことができます｡
‫では､ ここからゲームスタート時にゲームイベントマネージャーを呼び出したいとします｡
‫では､ 次にコードを実行してみましょう｡
‫まだIDがDragon Silver Dragon Dongというスポーツ選手｡
‫ドラゴンドッグとドラゴンドッグを使ったスポーンプレイを開始しました｡
‫まず､ 「Kes」というプログラムによってイベントが発生し､ 次に最後のプレイヤーである「ドラゴン犬」によって､
‫再び「On Game Start」が呼び出されたのですね｡
‫ここでは､ 基本的にそのようなことが起こっているわけです｡
‫だから､ ここは本当に気をつけないといけない｡
‫それは､ 直すのが超難しいことなんです｡
‫つまり､ イベントをprivateにすることはできません｡ クラスのコンストラクタでイベントを購読するためにはpublicである必要があるからです｡
‫これまでデリゲートについて話すときはイベントという名前を使っていましたが､ これはデリゲートが文字通りイベントのように振る舞っていたからです｡
‫しかし､ 実はイベントという特殊なデリゲートがあり､ このような失敗を防ぐために作られているのです｡
‫わかりました｡
‫というのも､ ゲームイベントマネージャで作成したこのデリゲートは､
‫基本的にこの公開学習ゲームイベントがイベントだからです｡
‫つまり､ ここでこのイベントキーワードを使えば､
‫このミスを防ぐことができるのです｡
‫しかし､ イベントに関しては､ サブスクライブすることしかできないので､ このイベントを直接呼び出すことはできない｡
‫ゲームイベントマネージャーから直接トリガーされるため､ イベントを直接呼び出すことができなくなりました｡
‫Game Startはイベントとなり､ 作成したクラス内からのみ呼び出すことができるようになりました｡
‫そしてまた､ それをリストのように扱うことを強要しているのです｡
‫ですから､ 等号の左側にイベントを持つことは許されません｡
‫だから､ 今回のようなことは､ これまで見てきたように､ 許されないことなのです｡
‫さて､ もう一度アプリを実行してみると､ 完璧に動作していることがわかりますね｡
‫コードを実行させてください｡
‫そして､ それは完全にうまくいきました｡
‫今回は､ デリゲート､ マルチキャストデリゲート､ イベントを1つのビデオにまとめましたので､ 非常に凝縮された例であり､ かなりシンプルな例となりました｡
‫しかし､ このビデオで､ デリゲートとイベントを扱う際にどのような利点があるのか､ おわかりいただけたと思います｡
‫そして､ デリゲートとイベントの作り方はもうお分かりだと思います｡
‫例えば､ 何かをクリックしているときにイベントが発生し､ 複数のものがサブスクライブすることができます｡
‫複数のメソッドは､ 例えばボタンがクリックされたり､ キーボードのいずれかのキーがクリックされたりすると､
‫トリガーされたそのイベントをサブスクライブして､ 一旦実行することができます｡
‫さて､ それでは本当に簡単にまとめてみましょう｡
‫イベントとは､ リストのように振る舞うことを強制されたデリゲートの制限された形であり､ そこからメソッドを追加したり削除したりすることができるだけで､
‫プラスイコールやマイナスイコール記号を使ってサブスクライブやアンサブスクライブを行うことはできますが､ イコール記号を使うことはできません｡
‫デリゲートは､ 私のデリゲートと私のメソッドを等しくすることで､ 直接的な代入を可能にします｡
‫そうすることで､ それまで追加されていた他のどのようなメソッドも置き換わる｡
‫だから､ ここは慎重に｡
‫また､ イベントは､ それを定義したクラスの外からしか呼び出すことができません｡
‫それらには､ メソッドの登録と未登録しかできません｡
‫さて､ このビデオでイベントや代表者についてよく理解していただけたと思いますので､ 次のビデオでお会いしましょう｡