Unity3d对象池技术的实现Demo

不管何种语言,对象的创建与销毁都需要消耗一定的时间,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));
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容

  • Java对象的生命周期分析 Java对象的生命周期大致包括三个阶段: 对象的创建 对象的使用 对象的清 因此,对象...
    jiangmo阅读 3,474评论 1 3
  • Unity 对象池技术 为什么使用对象池? 在我们开发中,往往会遇见需要不断创建和销毁同一物体的情况。(如飞机大战...
    胤醚貔貅阅读 788评论 0 0
  • (一) 装,装腔作势和服装,有着同样的“装”,却装的不同。 从出生,我就开始了“装”,装作听话的小孩,让父母省心。...
    果慧_631e阅读 381评论 4 1
  • 来英三年,机缘巧合发现了一个古迹版的 Airbnb 机构 Landmark Trust,让我这种有精品酒店情结、又...
    纳谷nakko阅读 650评论 2 7
  • 作者:简言君赵鹏 人不能无缘无故拥有一件好东西。所以,每当我看到一个很喜欢的东西时,便会问自己:你凭什么拥有它? ...
    简言君赵鹏阅读 682评论 1 14