Unity Asset PoolManager使ってみた

PoolManager
32ドル。AssetStoreにたくさんのObject Pool Scriptが販売されているけど皆10ドルくらい。32ドルは破格の値段だ
![2017-02-26 20.53.19.jpg](https://qiita-image-store.s3.amazonaws.com/0/67575/46716dc8-e251-677f-2ffd-67075da9c482.jpeg)

アセットストア
https://www.assetstore.unity3d.com/jp/?#!/content/1010
ドキュメント
http://poolmanager.path-o-logical.com/

##特徴
###Pool Instance
PoolInstance。これにはInstantiate/Destroy関数の代わりとなるSpawn/Despawn関数が用意されている。これを使うことでGCを回避する
Pool Pre-Runtime Instanceを設定することで事前にシーン上に配置しておくPoolInstance数を決定できる。

###簡単なセットアップ
SpawnPoolコンポーネントをもったPoolManager GameObjectをシーンに配置する。
あと
Instantiate関数 -> Spawn関数
Destroty関数 -> Despawn関数
に置き換える。

###uGUI,Audio,Particle SystemもPool可能

##使ってみる
###セットアップ
Documentを参考に
Documentが割と丁寧に書いてあるのでうれしい。
http://docs.poolmanager.path-o-logical.com/home/1-start-pooling-spawn-despawn

Pool管理用に適当なGameObjectを作成し、SpawnPoolコンポーネントをAddする。
SpawnPoolコンポーネントのPoolNameパラメータに適当な名前を付ける。

- Match Pool Scale
PoolObject生成時にPoolObjectのLocalScaleを1にするか
- Match Pool Layer
PoolObject生成時にPoolObjectとその子要素のLayerをSpawnPoolコンポーネントを持つGameObjectのLayerと同じにするか
- Don't Destroy On Load
SpawnPoolコンポーネントとPoolしているGameObjectをDontDestoryOnLoadにするか。既に同じSpawnPoolオブジェクトがDontDestoryOnLoadされているかどうかに限らずこのフラグがOnだとDontDestoryOnLoadされる。
タイトルシーンでDontDestoryOnLoadしてて、ゲームシーンでPool使った後にまたタイトルシーンに行くとSpawnPoolオブジェクトが増えている気がする。


とりあえずセット
適当なCubeのPrefabを作成し、Pre-Prefab-Poolにセット。preload Amountに10をセットしてゲーム起動時に10個ほど生成されるようにした。
PoolNameにTestCubeと入力。
![2017-02-26 23.51.32.jpg](https://qiita-image-store.s3.amazonaws.com/0/67575/d01f10bb-b9a6-c5fe-9290-e5fba82b5109.jpeg)

ゲーム再生。
ちゃんと10個Insntanceが作られた。（InActive）
![2017-02-26 23.55.05.jpg](https://qiita-image-store.s3.amazonaws.com/0/67575/ac1f2284-df0c-a8d9-83c2-fc1999b7c181.jpeg)

###PoolされたPrefabをSpawnする

```
	public GameObject cubePrefab;

	Transform poolInstance;
	// Use this for initialization
	void Start()
	{
		var spawn = PoolManager.Pools["TestCube"];
		var cube = spawn.Spawn(cubePrefab);
		poolInstance = cube;
	}
```

###SpawnしたPrefabをDespawnする

```
	void Update()
	{
		if (Input.GetKeyUp(KeyCode.Space))
		{
			if (PoolManager.Pools["TestCube"].IsSpawned(poolInstance))
			{
				PoolManager.Pools["TestCube"].Despawn(poolInstance);
			}
		}
	}
```

メンバ変数であるpoolInstanceにspawnさせたPrefabのインスタンスをセットしていたけど、こいつを使ってNullチェックしてはいけない。Despawnした後もこいつのInstanceは削除されないのでnullにはならないからだ。代わりにPoolManager.Pools["hoge"].IsSpawned(pooledobj)を使用する。

```
			//悪い
			if(poolInstance != null)
			{
				//hogehoge
			}

			//良い
			if (PoolManager.Pools["TestCube"].IsSpawned(poolInstance))
			{
				//hogehoge			
			}

```

##大量にSpawnさせてみる。
SpaceKeyを押したときにSpawnさせるようにした。
PreLoad数を超えてSpawnすると新しいPrefabInstanceが用意される。

![2017-02-27 00.04.04.jpg](https://qiita-image-store.s3.amazonaws.com/0/67575/e49fa81b-be1e-5f1e-974c-a05630c51b36.jpeg)

##Spawnする順番
PreLoadしたPrefabの各InstanceはPreLoadさせたSpawnPoolオブジェクトの子要素になる。Spawn関数が呼ばれた場合はPreLoadした順で（子要素のIndex0から）Instanceが返される。ただし一度使ったInstanceの取得順は最後に回される。

##Spawn/Despawn時の初期化/終了処理
適当なコンポーネントにOnSpawned/OnDespawned関数を付けてCubePrefabにAddする。
内部でBroadcastMessageをしている。これで初期化・終了処理ができる。

```
using PathologicalGames;

public class TestCube : MonoBehaviour {
	private void OnSpawned(SpawnPool pool)
	{
		Debug.Log
		(
			string.Format
			(
				"OnSpawnedExample | OnSpawned running for '{0}' in pool '{1}'.",
				this.name,
				pool.poolName
			)
		);
	}

	private void OnDespawned(SpawnPool pool)
	{
		Debug.Log
		(
			string.Format
			(
				"OnSpawnedExample | OnDespawned unning for '{0}' in pool '{1}'.",
				this.name,
				pool.poolName
			)
		);
	}
}

```