unity开发unity3D技术分享征服Unity3d

Unity3d对象池技术的实现Demo

2016-06-18  本文已影响1289人  好怕怕

不管何种语言,对象的创建与销毁都需要消耗一定的时间,Unity3D 也是如此,所以在场景中,如果某些对象需要频繁的创建与销毁,这个时候我们经常采用对象池技术,这样不仅可以降低对象的创建与销毁的带来的时间损耗,也是为了降低内存的占用。 我们在做项目的时候,如果同一个物体要用到好多次,我们就不要再用实例化了,因为每次创建一个新物体是很消耗资源的,引用对象池技术,顾名思义,把所有要用到的对象在初始化的时候都扔到这个池子里,想用的时候拿出来用,不想用的时候放回去,这样会大大节省资源!
【一共是一个Demo,两个版本,一个是一个对象的储存与获取,另一个版本是多个游戏对象的储存与获取,都写在一个类中的,下面就为大家分享一下对象池的实现】
DemoName:ObjectPool
Demo下载地址:http://pan.baidu.com/s/1kVdGLHd

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

/// <summary>
/// 对象池管理脚本,无需挂载
/// </summary>
public class ObjectPools
{
    #region 对象池

    /// <summary>
    /// 对象池1,创建单个对象
    /// </summary>
    List<GameObject> pools1;

    /// <summary>
    /// 以字典的方式储存对象到池中,int类型key,集合类型的value
    /// </summary>
    Dictionary<int, List<GameObject>> pools2;

    //单例
    private static ObjectPools singleton;

    /// <summary>
    /// 获取对象,单例
    /// </summary>
    /// <returns></returns>
    public static ObjectPools GetInstance()
    {
        if (singleton == null)
        {
            singleton = new ObjectPools();
        }
        return singleton;
    }

    //构造函数初始化对象池
    public ObjectPools()
    {
        pools1 = new List<GameObject>();
        pools2 = new Dictionary<int, List<GameObject>>();
    }

    #endregion

    #region 储存单个游戏对象到池中

    /// <summary>
    /// 储存单个游戏对象到池中
    /// </summary>
    /// <param name="gameObject">创建的游戏对象</param>
    /// <param name="pos">位置</param>
    /// <param name="rotation">旋转</param>
    /// <returns>返回的对象</returns>
    public GameObject SwpanObject(GameObject gameObject, Vector3 pos, Quaternion rotation)
    {
        //如果池中的对象数量大于0
        if (pools1.Count > 0)
        {
            GameObject result = pools1[0]; //提取第一个对象
            pools1.Remove(result); //从集合中清除提取的对象
            result.SetActive(true); //设置当前对象激活
            result.transform.position = pos; //设置对象的初始位置
            result.transform.rotation = rotation; //设置对线下的初始旋转
            return result; //返回游戏对象
        }
        //否则,直接实例化游戏对象并返回
        return GameObject.Instantiate(gameObject, pos, rotation) as GameObject;
    }


    /// <summary>
    /// 隐藏当前游戏对象并添加到池中
    /// </summary>
    /// <param name="gameObejct">游戏对象</param>
    public void DestoryObject(GameObject gameObejct)
    {
        //关闭当前游戏对象显示
        gameObejct.SetActive(false);
        //添加到集合中
        pools1.Add(gameObejct);
    }

    #endregion

    #region 储存多个游戏对象到池中

    /// <summary>
    /// 实例化并储存游戏对象到池中
    /// </summary>
    /// <param name="gameObject">被创建的游戏对象</param>
    /// <param name="pos">位置</param>
    /// <param name="rotation">旋转</param>
    /// <returns>返回当前游戏对象</returns>
    public GameObject SwpanObject2(GameObject gameObject, Vector3 pos, Quaternion rotation)
    {
        //获取到当前对象的ID(每个游戏对象都有各自的ID)
        int key = gameObject.GetInstanceID();
        //如果池中包含key当前游戏对象的key值(游戏对象的ID)
        if (pools2.ContainsKey(key))
        {
            //如果池中的对象数量大于0
            if (pools2[key].Count > 0)
            {
                //提取第一个对象(key就是ID(ID就是相对应的游戏对象),0代表的是这个key中第一个对象)
                GameObject result = pools2[key][0];
                result.SetActive(true); //激活显示当前对象
                pools2[key].Remove(result); //从池中清除对象游戏对象
                result.transform.position = pos; //设置初始位置
                result.transform.rotation = rotation; //设置初始旋转
                return result; //返回提取的游戏对象
            }
        }
        //否则,实例化对象并接收
        GameObject res = GameObject.Instantiate(gameObject, pos, rotation) as GameObject;
        //储存游戏对象的ID,转换成字符串
        res.name = gameObject.GetInstanceID().ToString();
        //返回场景的游戏对象
        return res;
    }


    /// <summary>
    /// 隐藏当前游戏对象并添加到池中
    /// </summary>
    /// <param name="gameObject">游戏对象</param>
    public void DestoryObject2(GameObject gameObject)
    {
        //当前游戏对象不激活
        gameObject.SetActive(false);
        //获取当前游戏对象的key值,转换成int类型
        int key = int.Parse(gameObject.name);
        //如果池中不包含key值对应的游戏对象
        if (!pools2.ContainsKey(key))
        {
            //添加对象到池中,并开辟value空间
            pools2.Add(key, new List<GameObject>());
        }
        //否则直接添加key对应的游戏对象到池中
        pools2[key].Add(gameObject);
    }

    #endregion

    #region 协程,延迟关闭游戏对象的显示

    /// <summary>
    /// 协程,延迟隐藏游戏对象,单个游戏对象
    /// </summary>
    /// <param name="gameObject">隐藏的游戏对象</param>
    /// <param name="time">隐藏的时间间隔</param>
    /// <returns></returns>
    public IEnumerator IEDestory(GameObject gameObject, float time)
    {
        yield return new WaitForSeconds(time);
        GetInstance().DestoryObject(gameObject);
    }

    /// <summary>
    /// 协程,延迟隐藏游戏对象,游戏对象数组
    /// </summary>
    /// <param name="gameObject">隐藏的游戏对象</param>
    /// <param name="time">隐藏的时间间隔</param>
    /// <returns></returns>
    public IEnumerator IEDestory2(GameObject gameObject, float time)
    {
        yield return new WaitForSeconds(time);
        GetInstance().DestoryObject2(gameObject);
    }
   #endregion
}
using UnityEngine;

/// <summary>
/// 对象池的调用,挂载到空物体即可
/// </summary>
public class GameManager : MonoBehaviour
{
    //储存单个游戏对象到对象池中
    public GameObject player;

    //需要利用到对象池的游戏对象数组(同时创建多个游戏对象)
    public GameObject[] players;


    void Update()
    {
        //单个游戏对象的插件
        if (Input.GetMouseButtonDown(2))
        {
            //按下鼠标中键的时候创建一个游戏对象
            GameObject go =
                ObjectPools.GetInstance().SwpanObject(player, Vector3.zero, Quaternion.identity) as GameObject;
            //开启协程,延迟隐藏对象
            StartCoroutine(ObjectPools.GetInstance().IEDestory(go, 2f));
        }

        //游戏对象数组的创建
        if (Input.GetMouseButtonDown(0))
        {
            //按下左键,创建数组中第1个游戏对象
            GameObject go = ObjectPools.GetInstance().SwpanObject2(players[0],
                Vector3.zero, Quaternion.identity);

            //开启协程,延迟隐藏对象
            StartCoroutine(ObjectPools.GetInstance().IEDestory2(go, 2f));
        }

        if (Input.GetMouseButtonDown(1))
        {
            //按下右键,创建数组中第2个游戏对象
            GameObject go = ObjectPools.GetInstance().SwpanObject2(players[1],
                Vector3.zero, Quaternion.identity);
            //开启协程,延迟隐藏对象
            StartCoroutine(ObjectPools.GetInstance().IEDestory2(go, 2f));
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读