どうもです、タドスケです。
以下の本を読了したので、学んだ内容をまとめておきます。
概要
デザインパターンを実際のゲーム開発で活用するための具体的なメニューが紹介されています。
デザインパターン
本書の中では多くのデザインパターンが紹介されていましたが、
僕にとって特に学びの多かったパターンに絞って載せておきます。
コマンド
オブジェクトに対するリクエストをコマンドクラスとして扱う。
例えばキャラクターの移動をCommandMoveクラスとして実装する。
操作されるオブジェクト側で抽象クラスCommandのキューを持っておけば、コマンドを順番に処理できる。
実行済みのコマンド履歴を残しておけば、アンドゥ操作も簡単にできる。
シングルトン
一つしかない存在しないオブジェクトを表現するためのものだが、現場では単にグローバル変数の代わりとして乱用されがち…。
下手に使うとクラス間の結合度を上げる原因になってしまう。
UIやサウンドのクラス内でEnemyManagerを取ってきたりするのはダメなパターン。
これらは外部から呼んでもらうことに専念するべき。
安易にシングルトンを選択するのではなく、
オブジェクトの参照を外部から引き渡したり、共通のクラス経由でGetしてくるようにできないかを検討した方が良い。
ステート
状態をenumではなくクラスで表現する。
現場ではシーケンスをモード変数enumとswitchで処理するケースが多い。
簡単なシーケンスなら手っ取り早くて良いが、長いシーケンスだとコードの肥大化を招きがち。
適宜クラスを分割して一つのクラス内のコードを短く保つようにしていきたい。
バイトコード
ゲーム内に独自のスクリプト実行環境を作る。
敵キャラの行動などを簡単なスクリプトで書いたりできる。
プランナーが直接挙動を制御できるようになるので柔軟性が上がるが、
やり過ぎるとプランナーにプログラムを書かせているのと大差なくなってしまう。
RPGツクールのようにマウスで設定できるコマンド方式がちょうど良いラインかもしれない。
コマンドパターンと組み合わせるのも面白そう。
コンポーネント
各機能を部品=コンポーネントとして扱い、
オブジェクトにさせたい処理に応じて必要なコンポーネントを持たせるようにすることで、
オブジェクトの挙動をコンポーネントの組み合わせで表現できる。
例えばエネミークラス内でサウンドの関数を直接呼ぶのではなく、
サウンドコンポーネントクラスを作ってエネミーに持たせる。
実際のサウンド処理はコンポーネントに委譲する。
Unityはこの考え方で作られている。(スクリプトもコンポーネントの一つでしかない)
継承を使うよりも柔軟性が高いので、継承でないといけない部分以外はコンポーネントで実装できないか検討したい。
肥大化したクラスの整理にも有用。
サービスロケータ
グローバル変数やシングルトンで直接クラスにアクセスする代わりに、
窓口クラスを設けてそこから取得できるようにする。
取得関数内の実装を変えることで、利用者に影響せずに実体を差し替えることができる。
SoundManagerを取得させるのではなく、
外部向けに機能を限定したインターフェースISoundManagerを返すようにすれば、モジュール間の結合を下げることも可能。
ただし使い過ぎるとシングルトンと変わらないので注意が必要。
感想
デザインパターン自体は若手の頃にもWebなどから学んでいましたが、
・これどこで使えるの?
・なんでわざわざこんな回りくどいことしてるの?
としか思いませんでした。
しかし10年以上現場でプログラミングを行い、他の人のコードにも触れていくうちに、
・このパターン、あそこで使われてたやつだ!
・あの部分の実装にこのパターンを使えばもっとキレイに書けそう!
という発見がありました。
本は読むタイミングによって違った学びがあるという話は聞いていましたが、まさに今回それを実感できた次第です。
この本が理解できたことをきっかけに、過去に読んだけどよくわからなかった本を再度読み直してみようかなと思えるようになりました。
コメント