オブジェクトプール

  • 2025年2月22日
  • 2025年3月13日
  • Unity
  • 10View
  • 0件

オブジェクトプールは、Unityで複数のオブジェクトの生成と削除を繰り返すことで発生するメモリ負荷を軽減する仕組みです。必要なオブジェクトを事前に用意し、それ以上は生成しないように管理することで、パフォーマンスの低下を防ぎます。

Unityには標準のオブジェクトプール機能があり、スタックやキューを用いた自前の実装方法もありますが、今回はUnity標準の使い方について解説します。

オブジェクトプールの仕組み

このオブジェクトプールの仕組みは以下のように動作します:

  1. ゲーム開始時に、指定された最大数のオブジェクトを事前に生成。
  2. 使用するオブジェクトが必要になったら、プールから取得。
  3. オブジェクトを使用後、一定時間経過するとプールに戻す。
  4. 必要に応じて新しいオブジェクトを生成(上限を超えない範囲で)。

オブジェクトプールの実装サンプル

① プールを管理するスクリプト

このスクリプトは、オブジェクトプールの作成、取得、返却、破棄を管理します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;

public class MyObjectPool : MonoBehaviour {
    // プールするオブジェクトのPrefab
    public GameObject prefab;
    
    // UnityのObjectPool (GameObject型)
    private ObjectPool<GameObject> objectPool;
    
    void Start() {
        // オブジェクトプールを作成
        objectPool = new ObjectPool<GameObject>(
            CreateObject,  // 新しいオブジェクトを作成する関数
            GetObject,     // 取得時に実行する処理
            ReleaseObject, // 解放時に実行する処理
            DestroyObject, // 破棄時に実行する処理
            true,          // コレクション用に自動拡張するか
            10             // 初期プールサイズ
        );
    }
    
    // オブジェクトを取得する
    public GameObject Get() {
        return objectPool.Get();
    }
    
    // オブジェクトをプールに戻す
    public void Release(GameObject obj) {
        objectPool.Release(obj);
    }
    
    // 新しいオブジェクトを作成する
    private GameObject CreateObject() {
        return Instantiate(prefab, transform.position, Quaternion.identity, transform);
    }
    
    // プールから取得時に行う処理(オブジェクトを有効化)
    private void GetObject(GameObject obj) {
        obj.SetActive(true);
    }
    
    // プールに戻す際に行う処理(オブジェクトを無効化)
    private void ReleaseObject(GameObject obj) {
        obj.SetActive(false);
    }
    
    // オブジェクトが不要になった場合に破棄する
    private void DestroyObject(GameObject obj) {
        Destroy(obj);
    }
}

② プールからオブジェクトを取得するスクリプト

このスクリプトは、スペースキーを押すとオブジェクトを取得し、ランダムな位置に配置後、3秒後にプールに戻します。

using System.Collections;
using UnityEngine;public class ObjectPoolTest : MonoBehaviour {
// MyObjectPool(オブジェクトプールのスクリプト)への参照
public MyObjectPool objectPool;

void Update() {
// スペースキーが押されたらオブジェクトを生成
if (Input.GetKeyDown(KeyCode.Space)) {
SpawnObject();
}
}

// オブジェクトをプールから取得してランダムな位置に配置
private void SpawnObject() {
GameObject obj = objectPool.Get(); // プールからオブジェクトを取得
obj.transform.position = new Vector3(Random.Range(-5f, 5f), 1f, Random.Range(-5f, 5f)); // ランダムな位置に配置

// 一定時間後にオブジェクトをプールに戻す
StartCoroutine(ReturnToPool(obj, 3f));
}

// 指定した時間後にオブジェクトをプールに戻すコルーチン
private IEnumerator ReturnToPool(GameObject obj, float delay) {
yield return new WaitForSeconds(delay); // 指定した秒数待機
objectPool.Release(obj); // オブジェクトをプールに戻す
}
}

③ スクリプトをオブジェクトにアタッチ

スクリプトアタッチ
Unityエディター画面

④ 実行結果

このオブジェクトプールを実行すると、以下のような動作が確認できます:

  1. スペースキーを押すと、オブジェクトがランダムな位置に生成されます。
  2. 生成されたオブジェクトは3秒間その場に留まります。
  3. 3秒経過すると、オブジェクトは非アクティブ化され、プールに戻ります。
  4. 再度スペースキーを押すと、プール内のオブジェクトが再利用され、再び表示されます。
実行結果

オブジェクトプールのメリット

  1. メモリの使用量を削減
  2. パフォーマンスの向上
  3. GC(ガベージコレクション)の抑制

まとめ

Unityのオブジェクトプールを活用することで、オブジェクトの生成コストを削減し、ゲームのパフォーマンスを向上させることができます。特に、シューティングゲームの弾やエフェクトの管理に最適です。

最新情報をチェックしよう!