ヨイチカの冒険譚

日々の思い付きを日記のように書き留めていく

オブジェクトプール

前置き

オブジェクトプールを学んだので備忘録。
最近デザインパターンの本よく読んでだいぶ知見たまってきたのでブログどんどん更新していく(予定)

オブジェクトプールとは

オブジェクトを生成してそのオブジェクトを使いまわすことで重い処理である生成や破棄を抑えて負荷を下げようというときに使うものです。(※間違っていたらすいません)
プールしすぎるとメモリを多く使うことになるのでそこは注意が必要かもしれません。

汎用的なオブジェクトプールのロジック

Unityではオブジェクトプールはプールするオブジェクトの親として空のオブジェクトを生成しておき、そこから子としてプーリングしていく感じが多い印象です。
使う際はアクティブと非アクティブを切り替えて再利用しています。

コード
 public class MyObjectPool : MonoBehaviour
    {
        //プールとなる親オブジェクト
        private Transform _pool;
        
        private void Start()
        {
            _pool = new GameObject($"Pool").transform;
        }
     
        void GetPoolObject(GameObject gameObject)
        {
            foreach (Transform transform in _pool)
            {
                //オブジェクトが非アクティブなら使いまわす
                if (!transform.gameObject.activeSelf)
                {
                    //処理
                    transform.gameObject.SetActive(true);
                }
                
                //非アクティブがない時は生成する
                Instantiate(gameObject,_pool);
            }
        }
    }

まとめ

オブジェクトプールの汎用的なものを作ろうと考えて試行錯誤していたのですが、結局なにをプールするかで処理が全然違ってくるため、汎用化は自分のレベルでは無理でした…
ジェネリクスを使って継承する形でオーバーライドで処理を書いていくのを思いつくのがやっとでした。

継承したバージョン(そんな変わってない)

  public class MyObjectPool<T> : MonoBehaviour
    {
        //プールとなる親オブジェクト
        protected Transform _pool;

        [SerializeField, Header("生成数")] protected int _generateCount;
        
        private void Start()
        {
            _pool = new GameObject($"{typeof(T).Name}Pool").transform;
        }

        protected virtual void GenerateObject()
        {
            for (int current = 0; current < _generateCount; current++)
            {
                //生成処理
            }
        }

        protected virtual void GetPoolObject(GameObject gameObject)
        {
            foreach (Transform transform in _pool)
            {
                //オブジェクトが非アクティブなら使いまわす
                if (!transform.gameObject.activeSelf && transform)
                {
                    //処理
                    transform.gameObject.SetActive(true);
                }
            }
        }
    }