ObjectPool
MRTKのUtilitiesにはちょいちょい便利なものが入っており,ObjectPoolもその一つです。
UnityのObjectPool関連資料はけっこうヒットするので,説明はそちらにお任せします。
この3つのクラスが重要になります。
- GameObjectPool.cs
- GameObjectCreator.cs
- IGameObjectListener.cs
使い方
GameObjectCreatorを継承してクラスをつくる
AbstractクラスであるGameObjectCreatorを継承して生成ロジックを書きます。
今回,Cubeを生成するCubeCreatorを作りました。
/// <summary> /// GameObjectCreatorを継承して生成のロジックを書く /// </summary> public class CubeCreator : GameObjectCreator { public override GameObject Instantiate() { return GameObject.CreatePrimitive(PrimitiveType.Cube); } }
GameObjectPoolを作る
pool生成し,先ほど作ったCubeCreatorを識別子つきで登録します。
/// <summary> /// Poolを生成する /// </summary> var pool = new GameObjectPool(); //Poolに生成を担うクラスを識別子つきで登録する pool.AddCreator(new CubeCreator(), "Cube");
GameObjectを生成する
使う時は,識別子を指定してGameObjectを取り出します。Poolにオブジェクトがもう残っていなければ,新規にオブジェクトを生成します。
pool.GetGameObject("Cube", Vector3.one, Quaternion.identity);
これを呼び出すたびにCubeが生成されます。
使い終わったGameObjectをPoolに保存する
オブジェクトプールに使い終わったGameObjectをRecycleで保存します。Destroyではなくfalseになるだけです。
//生成する var cube = pool.GetGameObject("Cube", Vector3.one, Quaternion.identity); //使い終わったら識別子を指定して,ObjectPoolに保存 pool.Recycle(cube, "Cube");
再度GetGameObjectで取り寄せようとすれば,enabled = falseになっているものから取り出してactiveにしていきます。足りなくなったら再度生成します。
var cube = pool.GetGameObject("Cube", Vector3.one, Quaternion.identity);
大まかな使い方は以上です。
もう少し掘り下げます。
Abstract class である,GameObjectCreatorの中身です。今回は生成処理の Instantiate() だけを触りましたが,Poolから取り出すときにはPrepareForUseが,返す時はPrepareForRecycleと,それぞれで処理が走っています。
public abstract GameObject Instantiate(); public virtual void PrepareForRecycle(GameObject obj) { var components = obj.GetComponents<MonoBehaviour>(); foreach (var component in components) { if (component is IGameObjectCreatorListener) { (component as IGameObjectCreatorListene).PrepareForRecycle(); } } } public virtual void PrepareForUse(GameObject obj) { var components = obj.GetComponents<MonoBehaviour>(); foreach (var component in components) { if (component is IGameObjectCreatorListener) { (component as IGameObjectCreatorListene).PrepareForUse(); } } }
Recycle,Useをする対象のオブジェクトが,IGameObjectListenerを実装したコンポーネントがアタッチされていれば,active, deactive 前に処理を呼び出してくれるようになっています。
また,今回GameObjectCreatorを継承してわざわざクラスを作りましたが,基本生成するオブジェクトを指定するというのは変わらないため,GenericPrefabInstanceCreatorという予めメンバにPrefabを指定できるクラスも用意されており,こんな感じに書けます。凝ったことをしたい訳でなければ基本,Genericで事足りると思います。
pool.AddCreator( new GenericPrefabInstanceCreator() { Prefab = prefab //生成してほしいPrefab }, "Cube");