genice26 发表于 2015-1-21 18:06

unity对象池(优化)

我们在做项目的时候,如果同一个物体要用到好多次,我们就不要再用实例化了,因为每次创建一个新物体是很消耗资源的,引用对象池技术,顾名思义,把所有要用到的对象在初始化的时候都扔到这个池子里,想用的时候拿出来用,不想用的时候放回去,这样会大大节省资源,我在蛮牛上看到一个写对象池不错的code,拿来分享一下。这个脚本非常简单,但它可以通过大量减少实例化所带来的开销使我的iOS游戏得到很大的性能提升。


[*]把脚本ObjectPool.cs链接到一个GameObject上。
[*]在物体预设数组中设置你想要放到池中并重复利用的预设物体。
[*]在缓冲数组中,指定你希望每个物体在游戏开始时被实例化的数量,这样在开始的时候你就有了池对象。
[*]在你的游戏中调用ObjectPool.instance.GetObjectForType(objectType,onlyPooled)来使用它。objectType写你想生成的预设的名字、并为onlyPooled指定布尔值,如果返回真,它将返回你已经放到池中的对象;如果返回假,它将实例化一个全新的对象。(如果你想限制被池对象的数量,那么设定为真,这样做非常有用,尤其是在需要限制同时播放特效的数量的时候)。
[*]确保你从池中调用的对象知道当它被删除时需要返回到池中。   

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

public class ObjectPool : MonoBehaviour
{

    public static ObjectPool instance;

    /// <summary>
    /// The object prefabs which the pool can handle.
    /// </summary>
    public GameObject[] objectPrefabs;

    /// <summary>
    /// The pooled objects currently available.
    /// </summary>
    public List<GameObject>[] pooledObjects;

    /// <summary>
    /// The amount of objects of each type to buffer.
    /// </summary>
    public int[] amountToBuffer;

    public int defaultBufferAmount = 3;

    /// <summary>
    /// The container object that we will keep unused pooled objects so we dont clog up the editor with objects.
    /// </summary>
    protected GameObject containerObject;

    void Awake ()
    {
      instance = this;
    }

    // Use this for initialization
    void Start ()
    {
      containerObject = new GameObject("ObjectPool");

      //Loop through the object prefabs and make a new list for each one.
      //We do this because the pool can only support prefabs set to it in the editor,
      //so we can assume the lists of pooled objects are in the same order as object prefabs in the array
      pooledObjects = new List<GameObject>;

      int i = 0;
      foreach ( GameObject objectPrefab in objectPrefabs )
      {
            pooledObjects = new List<GameObject>();

            int bufferAmount;

            if(i < amountToBuffer.Length) bufferAmount = amountToBuffer;
            else
                bufferAmount = defaultBufferAmount;

            for ( int n=0; n<bufferAmount; n++)
            {
                GameObject newObj = Instantiate(objectPrefab) as GameObject;
                newObj.name = objectPrefab.name;
                PoolObject(newObj);
            }

            i++;
      }
    }

    /// <summary>
    /// Gets a new object for the name type provided.If no object type exists or if onlypooled is true and there is no objects of that type in the pool
    /// then null will be returned.
    /// </summary>
    /// <returns>
    /// The object for type.
    /// </returns>
    /// <param name='objectType'>
    /// Object type.
    /// </param>
    /// <param name='onlyPooled'>
    /// If true, it will only return an object if there is one currently pooled.
    /// </param>
    public GameObject GetObjectForType ( string objectType , bool onlyPooled )
    {
      for(int i=0; i<objectPrefabs.Length; i++)
      {
            GameObject prefab = objectPrefabs;
            if(prefab.name == objectType)
            {

                if(pooledObjects.Count > 0)
                {
                  GameObject pooledObject = pooledObjects;
                  pooledObjects.RemoveAt(0);
                  pooledObject.transform.parent = null;
                  pooledObject.SetActiveRecursively(true);

                  return pooledObject;

                } else if(!onlyPooled) {
                  return Instantiate(objectPrefabs) as GameObject;
                }

                break;

            }
      }

      //If we have gotten here either there was no object of the specified type or non were left in the pool with onlyPooled set to true
      return null;
    }

    /// <summary>
    /// Pools the object specified.Will not be pooled if there is no prefab of that type.
    /// </summary>
    /// <param name='obj'>
    /// Object to be pooled.
    /// </param>
    public void PoolObject ( GameObject obj )
    {
      for ( int i=0; i<objectPrefabs.Length; i++)
      {
            if(objectPrefabs.name == obj.name)
            {
                obj.SetActiveRecursively(false);
                obj.transform.parent = containerObject.transform;
                pooledObjects.Add(obj);
                return;
            }
      }
    }

}

melliana2024 发表于 2017-2-27 15:02

很不错

小宝宝/ht 发表于 2017-2-27 15:38

楼主是超人

melliana2024 发表于 2017-2-27 15:09

好帖就是要顶

小白 发表于 2017-2-27 14:49

真心顶

cgjch8 发表于 2017-2-27 14:48

LZ真是人才

tt_55 发表于 2017-3-10 16:29

很不错

pincers 发表于 2017-3-10 16:43

好帖就是要顶

淡泊一笑 发表于 2017-3-10 16:32

真心顶

liangxinyu 发表于 2017-3-10 16:22

说的非常好
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: unity对象池(优化)