Zenjectのメモリプール

内容まとめ
1. はじめに
Zenjectのメモリプールは、 頻繁なオブジェクト生成と破棄によるガベージコレクションの発生を防ぐための仕組み
基本的な考え方として、ファクトリ(オブジェクトの生成)と同様のインターフェースを提供しつつ、生成済みのオブジェクトを再利用することで不要なヒープ割り当てを回避
2. Binding Syntax
メモリプールのバインディング構文は通常のファクトリバインディングとほぼ同様だが、以下のような追加オプションが利用可能
WithInitialSize / FixedSize
プールの初期サイズを指定し、必要な場合は固定サイズにすることで、動的な拡張や削除の挙動を制御
MaxSize
プールに返却されたアイテムがこのサイズを超えた場合、余分なインスタンスは破棄
ExpandBy
プールが空になった場合の挙動として、
- ExpandByOneAtATime … 1個ずつ新たなインスタンスを生成
- ExpandByDoubling … プールがいっぱいの際にサイズを倍増
WithFactoryArguments
メモリプール自体に追加の引数を渡すことが可能
ただし、実際に生成されるオブジェクトには WithArgumentsが適用される
3. プール内アイテムのリセット
プールから取得したオブジェクトは、前回の状態が残っている可能性があるため、再利用時にリセット処理を行う必要があり、メモリプール派生クラス内で以下のメソッドをオーバーライドして実装する
OnCreated(T item)
アイテムが初めてプールに追加された直後に呼ばれる
OnDestroyed(T item)
プールから完全に削除される際に呼ばれる(サイズ削減時など)
OnSpawned(T item)
プールから取得された直後に呼ばれる
OnDespawned(T item)
プールへ返却された直後に呼ばれる
Reinitialize(...)
実際のリセット処理として、パラメータ付きで再初期化する場合に利用される
5. Factory、Pool、Dispose パターン
従来のプール利用では、プール専用のサブクラスを作成し明示的に Spawn と Despawn を呼ぶ必要がある。これに対して、以下のようなパターンを利用することで、使う側のコードからプールの管理を隠蔽する。
IPoolable<T> インターフェース
OnSpawned と OnDespawned を実装し、プールからの取得・返却時に自動的にリセット処理を行う
IDisposable インターフェース
Dispose を呼ぶことで、自身をプールに返却するように実装する
6. ゲームオブジェクト用メモリプール
UnityのGameObjectをプールする場合は、MonoMemoryPoolクラスを利用する
このクラスは、GameObjectの有効化/無効化を自動的に管理する