(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!

    

オブジェクトを削除せずに再利用して負荷を減らす仕組み「オブジェクトプール」をUnityの標準機能で実装する【Unity】


このエントリーをはてなブックマークに追加


この記事でのバージョン
Unity 2022.2.2f1


はじめに

Unityではオブジェクトを生成する時にInstantiate、削除する時にDestroyを使いますが、

どちらもそれなりに重い処理なので出来るだけ実行回数を減らしたくなります。


そんな時に使えるのがオブジェクトプールという仕組みで、

使ったオブジェクトを削除せずに非表示にして、必要になったら再度表示して使うというものです。


以前そのオブジェクトプールをUniRxで実装するというのを紹介しましたが、


Unity2021からUnityの標準機能で実装出来るようになったので、



今回はこれの紹介です!


オブジェクトプールをUnityの標準機能で実装

さっそく使い方ですが、各処理をデリゲートとして渡してObjectPoolを作ります。

なお、例ではGameObjectのObjectPoolですが、他のクラスのプールを作る事ももちろん可能です。

//ObjectPoolを使うのに必要
using UnityEngine.Pool;
var pool = new ObjectPool<GameObject>(
  OnCreatePooledObject, //オブジェクトを生成する時の処理
  OnTakeFromPool,        //オブジェクトを取得する時の処理
  OnReturnedToPool,      //オブジェクトを開放する時の処理
  OnDestroyPoolObject,//オブジェクトを破棄する時の処理
  /*↓これ以降は省略可*/
  collectionCheck:true, //既に開放済みのオブジェクトを再度開放しようとした事をチェックするか(エラーを出すか)
  defaultCapacity:10,   //最初のプール(List)のサイズ、この数だけあらかじめオブジェクトが用意されるわけではない
  maxSize:10000         //プールする最大数(この数を超えたら破棄される = OnDestroyPoolObjectが実行される)
);


あとはGetでオブジェクトを取得し、そのオブジェクトが必要なくなったらReleaseで開放するだけ。

//プールからオブジェクト取得
var obj = pool.Get();
 
//オブジェクトを開放
pool.Release(obj);


各処理も具体的に書いてみると以下のような感じに。

//オブジェクトプールで使いたいPrefab(Inspectorで設定する)
public GameObject _prefab;

//=================================================================================
//初期化
//=================================================================================
 
private void Start() {
  //オブジェクトプールの準備
  var pool = new ObjectPool<GameObject>(
    CreatePooledItem, //オブジェクトを生成する時の処理
    OnTakeFromPool,        //オブジェクトを取得する時の処理
    OnReturnedToPool,      //オブジェクトを開放する時の処理
    OnDestroyPoolObject,//オブジェクトを破棄する時の処理
     /*↓これ以降は省略可*/
    collectionCheck:true, //既に開放済みのオブジェクトを再度開放しようとした事をチェックするか(エラーを出すか)
    defaultCapacity:10,   //最初のプール(List)のサイズ、この数だけあらかじめオブジェクトが用意されるわけではない
    maxSize:10000         //プールする最大数(この数を超えたら破棄される = OnDestroyPoolObjectが実行される)
  );
    
  //プールからオブジェクト取得
  var obj = pool.Get();
 
  //オブジェクトを開放(プールに戻す)
  pool.Release(obj);
}

//=================================================================================
//オブジェクトプールの各処理
//=================================================================================
    
//オブジェクトを生成する処理
private GameObject CreatePooledItem() {
  //Prefabからインスタンス作成
  return Instantiate(_prefab);
}

//オブジェクトを取得する時の処理
private void OnTakeFromPool(GameObject obj) {
  //オブジェクトを表示する
  obj.SetActive(true);
}

//オブジェクトを開放する時の処理
private void OnReturnedToPool(GameObject obj) {
  //オブジェクトを非表示にする
  obj.SetActive(false);
}
  
//オブジェクトを破棄する時の処理
private void OnDestroyPoolObject(GameObject obj) {
  //そのままDestory
  Destroy(obj);
}


ちなみにプールのオブジェクト数を取得する事や、

Debug.Log($"使われているオブジェクト数 : {pool.CountActive}");
Debug.Log($"使われいないオブジェクト数 : {pool.CountInactive}");
Debug.Log($"全オブジェクト数 {pool.CountAll}");


使われてないオブジェクトを一括で破棄する事も可能です。

//使われてないオブジェクトを一括で破棄(OnDestroyPoolObjectが実行される)
pool.Clear();