かずおの開発ブログ(主にRuby)

日々の開発のことを色々書きます。

簡易オブジェクトプール

UnityでGameObjectを生成、削除を行うInstatiateとDestroyメソッドゲーム制作においてよく使うメソッドだと思います。しかし、これらのメソッドは処理が重いので、大量に呼んでしまうとPCでは処理が早いのでうまくいっていても、実機に移すとガクガクとかくついてしまいます。 そこで使われるテクニックがオブジェクトプーリングです。

オブジェクトプーリングとは

Unityにおけるオブジェクトプーリングとは要らなくなったGameObjectをDestroyで削除するのではなく、SetAecive(false)で無効化して保持しておき、Instantiateでオブジェクトを生成する代わりに保持しておいたGameObjectを初期化、有効化して再利用するという方法です。これにより使えるオブジェクトがオブジェクトプールにないときにInstantiateが呼ばれる以外はInstantiateとDestroyが呼ばれることがなくなり処理が格段に軽くなります。 Unityのチュートリアルにもオブジェクトプールに関するものがあります。(http://japan.unity3d.com/developer/document/tutorial/2d-shooting-game/optimization/01.html)ただこれは少しややこしかったので、自身の理解のためにも今回はもう少しシンプルな簡易オブジェクトプールを作成したいと思います。

今回作成するもの

youtu.be

今回作成するのは上の動画のようにMaker(上にあるCube)から玉がどんどん出てきて、床にあたると消えるというシンプルなものをオブジェクトプールを用いて作成してみたいと思います。どんどん生成されているように見えますが、よく見るとBallの有効、無効が切り替わってプールされたオブジェクトが再利用されているのが分かるかと思います。

オブジェクトプールが導入前の状態

オブジェクトプールを作成する前に、まずオブジェクトプール導入前の状態を作ってみます。写真のようにヒエラルキー上にMakerオブジェクト、Floorオブジェクトを作成して、MakerオブジェクトにMaker.cs(InspectorでBallに玉のprefabをアタッチ、paceは0.3), 床オブジェクトにFloor.csオブジェクトをアタッチします。(Colliderのアタッチ、materialの作成など別途必要ですが割愛します) f:id:kazuooooo:20150517151811p:plain

gist.github.com

gist.github.com

スクリプトを見るとよくわかりますがこの状態だとMaker.cs側でInstantiateメソッド、Floor.cs側でDestroyメソッドをガンガン呼んでしまっていることわかるかと思います。このままだとかなり処理的に重くなってしまうので、ここにオブジェクトプールを導入していきます。

オブジェクトプールを作成

ではオブジェクトプールを導入していきましょう。 まずObjectPoolという名前で空のゲームオブジェクトを作成しましょう。そこに以下のObjectPool.csをアタッチします。Inspector上でBallPrefabには玉のprefabを、Makerにはヒエラルキー上のMakerを設定してください。

gist.github.com

ポイントはgetBallとreleaseBallメソッドです。これらのメソッドがそれぞれInstatiate, Destroyの代わりをします。 まずgetBallメソッドですが、ここでは a. オブジェクトプールに使えるものがあれば再利用する。 b. なければ生成してプールに追加する という処理を行っています。これによりプールに使える玉(非アクティブ)があるときはそれが初期化されてアクティブにされ、さも新たに生成したように見えます。 続いてreleaseBallメソッドですが、これは単純でオブジェクトをDestroyするのではなく、SetActive(false)で非アクティブにすることでプールに保持しておきます。

Makerスクリプト、Floorスクリプトを書き換え

ObjectPoolの準備が出来たら、仕上げにMakerスクリプトとFloorスクリプトを以下のように書き換えます。

gist.github.com

gist.github.com

これでInstantiateの代わりにgetBall、Destroyの代わりにreleaseBallが呼ばれるようになりました。

確認

最後に再生して確認してみましょう!動画のようballのアクティブが非アクティブが切り替わってどんどんボールが出て行く様子が分かるかと思います。ballの番号が上がっていかないことからオブジェクトがプールされて再利用されていることが分かります。 簡単ですが、概念を理解するのにはいいかと思います!お試しあれ!

activeInHierarchyについて activeSelf と activeInHierarchy についての解説 - 強火で進め