Unityパフォーマンス最適化のための簡単なキャッシュ・プールの書き込み

4018 ワード

会社でソースコードを見ていると、シュートのシーンで、プレイヤーはバスケットボールを絶えず投げ出し、オブジェクトを絶えず作成し、破棄していることがわかります.そこでキャッシュプールを書いて管理してみました.
PoolManagerというツールクラスのプラグインが便利に実現できますが、ここではUnity 3 D研究院の初のPoolManagerプラグインの紹介を見ることができます.
しかし、実際にはオブジェクトプールは事前にオブジェクトを作成しておき、必要に応じて取りに行けばいいのです.ない場合は、再作成します.使用後も廃棄されず、次回の使用に便利です.Androidのlistviewのholderに似ています.難しくないように見えて、少し時間をかけて書きました.
BufferPoolList.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class BufferPoolList{

    private List pool;
    private GameObject prefab;
    private Transform prefabParent;

    
    public BufferPoolList(GameObject obj, Transform parent, int count)
    {
        prefab = obj;

        pool = new List(count);
        prefabParent = parent;

        for (int i = 0; i < count; i++)
        {
            GameObject objClone = GameObject.Instantiate(prefab) as GameObject;
            objClone.transform.parent = prefabParent;//             
            objClone.name = "Clone0" + i.ToString();
            objClone.SetActive(false);
            pool.Add(objClone); 
        }
    }


    public GameObject GetObject()
    {
        //            
        foreach (GameObject iter in pool)
        {
            if (iter.activeSelf == false)
            {
                iter.transform.SetParent(prefabParent);
                iter.SetActive(true);
                return iter;
            }

        }
        GameObject newPrefab = GameObject.Instantiate(prefab) as GameObject;
        newPrefab.transform.SetParent(prefabParent);
        newPrefab.name = "Clone0" + pool.Count.ToString();
        newPrefab.SetActive(true);
        pool.Add(newPrefab);
        return newPrefab;
    }
}

Player上のスクリプトまたは制御クラススクリプトで初期化した後、我々が初期化した物体を使用する必要がある場合はGetObject()だけで、使い終わったら物体を非表示に設定すればよい.実例化された物体上で物体がスクリーン境界を超えているかどうかを判断することができ、超えている場合.SetActive(false);物体が見えないように設定します.
このように書くと、毎回オブジェクトを作成する必要はありませんが、キャッシュプールの目的は達成されていますが、使用可能なオブジェクトを取得するたびにループをして、なんだか変な感じがします.だから書き方を変えて、listではなく、Queueキューで書きます.コードは次のとおりです.
BufferPool.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class BufferPool
{
    private Queue pool;
    private GameObject prefab;
    private Transform prefabParent; 

    //           
    public BufferPool(GameObject obj,Transform parent,int count)
    {
        prefab = obj;
        
        pool = new Queue(count);
        prefabParent = parent;

        for (int i = 0; i < count; i++)
        {
            GameObject objClone = GameObject.Instantiate(prefab) as GameObject;
            objClone.transform.parent = prefabParent;//             
            objClone.name = "Clone0" + i.ToString();
            objClone.SetActive(false);
            pool.Enqueue(objClone);  
        }
    }

    
    public GameObject GetObject()
    {
        GameObject obj = null;

        if (pool.Count > 0)
        {
            obj = pool.Dequeue();  //Dequeue()           Queue       
            obj.transform.position = prefabParent.position;
        }
        else
        {
            obj = GameObject.Instantiate(prefab) as GameObject;
            obj.transform.SetParent(prefabParent);
           
        }
        
        obj.SetActive(true);
        return obj;
    }

    //    
    public void Recycle(GameObject obj)
    {
        obj.SetActive(false);
        pool.Enqueue(obj);//    
    }
}

これによりオブジェクトを取得する際にループを行わなくてもよい.使用するたびに、列を出します.インスタンス化された物体が使用されなくなった場合、キューに追加します.このように不便な点もあるが,ゲーム物体のスクリプトにPlayer上のBufferPool.csスクリプトを入手してオブジェクトを回収する必要があり,オブジェクトを取得する際には既にそのインスタンスをキューから削除しているので,使用しない場合はRecycleメソッドを呼び出してキューに入れる必要がある.
一つ用のリスト、一つ用のQueueですが、理屈は同じです.目的は,Unityインスタンス化対象が遅いという問題を解決するためである.
リンク:http://539go.com/2016/11/10/Unity-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8B%E5%86%99%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E7%BC%93%E5%AD%98%E6%B1%A0/