インベントリクラスの設計メモ

カテゴリ:unity

単純な実装

アイテムデータを格納するデータベースクラス(例えば ItemDB)を作成し, アイテムの情報が必要になるたびに,インデクサでそれにアクセスする. アイテムデータはファイル(最近では XML や JSON を使うことが多い)からロードされる.

プレイヤーの手持ちのアイテムは個数とアイテム ID とで表現する. あとはインベントリクラスを作成して機能を実装する.

問題点

この設計はインベントリクラスを肥大化させる; アイテムの効果をインベントリクラスに実装しなければならないからだ. そうするとクラス間の結合も強くなりテストもしづらくなる. アイテムの情報に直接アクセスする方法では,アイテム数が 100 を超えると管理が難しくなる.

アイテムを抽象化する

アイテムを抽象化してアイテムの効果を Use() に実装するようにすれば, インベントリクラスの肥大化は回避できる. ただしこの設計が通用するのは,アイテムが使用されて初めて効果があるものだけに限られる. 持っているだけで効果があるアイテムではまた別の設計 (たとえば初めて取得されたときに呼ばれる OnInventoryEnter など)が必要になる. 装備品は装備されないと効果が発揮されないので Use() だけで対応できる. そのほか GetName() 等のメソッドも必要なら追加する.

プレイヤーがアイテムを取得したとき,そのアイテム ID をアイテム DB に渡す. するとアイテム DB は適切なアイテムクラスを作成してインベントリクラスに渡す.

Use() が Delete を返す場合はインベントリから削除する. 使用可能性のチェックは Use 内で行われる.

アイテム効果の一般化

HP や空腹度などの単純なパラメータの増減や,単純な装備品はアイテムごとに処理を書く必要はない; ロジックが同じだからだ. 処理を共通化できると,その内容をアイテムファイルに直接記述できるようにするのも容易だ. 例えば "HP -10" という文字列を HP を 10 減らすメソッドにしたり, "hunger 50" を空腹度を 50 増加させるメソッドにしたりできる.

こうすることで特殊な効果だけをコード化すればよくなり, 柔軟性が増し,保守がやりやすくなる.

Effect Stack を使う

60 秒間攻撃力増加のポーションは普通,アイテムクラスに実装しないだろう. そのような効果はプレイヤーに現在ついているバフ・デバフを管理する EffectStack クラスを作ると便利だ. EffectStack クラスは IEffect クラスのコンテナで,毎フレーム AddEffect() を実行し, プレイヤーのステータスを補正する.

アイテムの効果もすべて EffectStack クラスで実行するようにできる. 装備は装備されている間有効なバフ効果として解釈できるし,消費アイテムは1回だけ実行されるエフェクトと解釈できる.

この実装のメリットはプレイヤークラスとの結合を切れることだ. アイテムクラスに直接実装する方法では何らかの方法でプレイヤーデータにアクセスする必要があったが, この方法では引数としてプレイヤーのデータにアクセスできる.