Unityでオブジェクトプールを利用して大量に使うオブジェクトの再利用
シューティングゲームを作っている時、弾を発射するときに生成(Instantiate)したり、被弾・画面外に出てしまったら破壊(Destroy)したりしていませんか?
そんなときはオブジェクトを生成・破壊を繰り返すのではなく、必要な量だけ最初に生成しゲーム中はそれを使い回すという方法を取ったりします。
それがオブジェクトプールと呼ばれる手法です。
今回はそれを実装してみたいと思います。
InstantiateやDestroyの処理はUnityではよく使われますが、それらの処理は重いと言われています。
少し前の記事ですが処理の速度を計算してくれている方がいました。
こちらですが見てみるとやはり時間がかかっています。
オブジェクトプールを使って少しでもゲームを軽くしていきましょう。
ちなみにこの処理を実装して作ったゲームはこちらになります。
またこの技術を使ったシューティングゲームの詳しい講座はこちらです。
この講座ではオブジェクトプール以外にも弾のパターンの作り方や、CSVをつかったステージの作り方など、ゲームづくりに役に立つ技を紹介してくれています。
オブジェクトプールの処理の流れ
前置きが長くなりましたが具体的にどういう処理をするのかを考えてみます。
- ゲーム開始時に親オブジェクトで必要な数だけ子オブジェクト(弾など)を画面外生成する
- 子オブジェクトを非表示にしておく
- 使いたいオブジェクト(Playerなど)から呼び出す
- 呼び出されたら親オブジェクトから子オブジェクトを貸し出す
- 使い終わったら回収し、再度非表示にする
この様な処理の流れになるかと思います。
では実際にこの仕組を作っていきましょう。
必要なオブジェクトの準備
それではUnityの新しい2Dプロジェクトを作りやっていきます。
必要となるゲームオブジェクトを作ります。
最低限これだけあればよいかと思います。
- 弾となるオブジェクト
- オブジェクトプール用の空オブジェクト
- 弾を呼び出すオブジェクト
現在この様な感じになっています。
白い丸がBulletで緑の四角がPlayerです。
ObjectPoolは空のゲームオブジェクトです。Positionはすべて0です。
弾のPrefab作成
次にBulletが移動していく処理を作成します。
BulletControllerというC#ファイルを作成しBulletにアタッチします。
中身についてはこのようにしておきます。
BulletのInspectorからSpeedを設定してあげましょう。
これで弾は上に移動していきます。
画面外に出たら回収する処理や、表示、回収の処理は後に記述していきます。
この段階でBulletをPrefab化してHierarchyから削除しておきます。
ObjectPoolの作成
次にObjectPoolを作っていきましょう。
ObjectPoolControllerというC#スクリプトを作成しHierarchy上のObjectPoolにアタッチします。
中身はこの様な感じにしました。
まず必要な変数を用意します。
そしてAwake関数でゲーム開始直後にQueueの初期化と弾Prefabの生成を行います。
ちなみになぜ生成時に画面外に配置するかというと、一瞬弾がゲーム上に表示されてしまう可能性があるからsetPosで画面外の座標を指定しています。
Launch関数ではVector3でポジションを受け取り、弾を渡します。
Collect関数では弾を回収して非表示にし、Queueに再度追加しています。
続いて先程作ったBulletController側に処理を書いていきます。
まず親のオブジェクトであるObjectPoolControllerを取得します。
続いてOnBecameInvisible、ShowInStage、HideFromStageの中身を記述しています。
この状態で一度ゲームを起動させてみると下のようになりました。
ObjectPoolの子要素としてBulletが非表示で生成されているのがわかると思います。
今回は100個生成しています。
Playerの作成
最後にPlayerから生成したBulletを呼び出してみます。
LauncherというC#スクリプトを作成しPlayerにアタッチします。
今回は特に「スペースキーを押したら発射」などではなくシンプルに開始時に発射するようにしてあります。
PlayerのInspectorから間隔を設定し起動してみましょう。
今回Intervalは0.3にしてみました
弾がプレイヤーの位置に渡され発射され、Hierarchyで順番に表示され画面外に出たら非表示になっているのが確認できるかと思います。
今回はPlayerの移動だったり弾が何かにあたった処理は実装していませんが、このようにしてオブジェクトを再利用することでInstantiateやDestroyを使う回数を減らしゲームを軽くすることができるようになります。
またオブジェクトプールは弾以外にも色々と使い道があると思いますので、大量のオブジェクトを使うことがある時は是非使ってみてください。
関連記事
TextMeshProでリンクを作成する方法とそのバグの解消法
今回はTMPのリンクを生成するLinkタグについて紹介したいと思います。
ちょっとしたハマりポイントもあるのでそちらについても触れていきたいと思います。
UnityでCSVを活用したメッセージウィンドウの作り方
メッセージの内容を変更したい時や、新しいメッセージを追加したい時にCSVファイルを使えば、メッセージの編集や追加が簡単になり、開発がスムーズになります。
Unity2D ドット絵の簡単なアニメーションを作ってみる
Unity2Dで簡単なドット絵のアニメーションを作成します。スプライトを切り替えることでプレイヤーが歩いているように見えるアニメーションを作成してみます。
この方法を応用することでキャラクターに色んな動きや表示を付け加えることができると思います。
ChatGPTの指示通りUnityゲームを作ってみる
最近ではChatGPTを始め様々な大規模言語モデルの対話型AIが公開されていますね。
そこで今回はChatGPTの指示に従ってゲームを作ってみる実験をしてみます。
Unityで9-sliceテクニックを使った効果的なUI作成方法
UI作成時に非常に便利なテクニック9-sliceをやってみます。
とても簡単に使える技です。
Transform.RotateとQuaternion.Eulerでオブジェクト回転
Unity2Dで簡単なゲームオブジェクトの回転を実装してみたいとおもいます。
Transform.RotateとQuaternion.Eulerの二種類の回転方法を実験します。
ルーレットとか、方位をコンパス。またはプレイヤーがやられた時に回転させるなどに使えそうです。
最後までご覧頂いてありがとうございました。