您的位置:首页 > 移动开发 > Unity3D

[置顶] unity中对象池的使用

2016-02-15 10:52 429 查看
在我们做游戏的时候,总会听到一些高大上的专业词汇,并且认为这些知识是很难学习的,其实不然,只要我们认真的学习它,总有拨开云雾的时候。

对象池:可以重复利用资源,不用不断的销毁生成对象,大大减少cpu开销,还可以避免内存泄露

对于对象池,我们也可以参考一下内存池的设计思路:http://blog.csdn.net/shawngucas/article/details/6574863

在学习对象池之前我们先要考虑什么地方会用到对象池:

(1)当需要不断重复的创建,删除同一个对象时;

(2)当在一个场景中有大量的怪物时,它们会释放技能;群体攻击技能时, 因为每个人身上都要产生一个技能特效。技能都是用粒子特效做的,虽然Unity中粒子特效也是一个GameObject.但是 Particle System这个组件太特殊了。Instantiate以后会自动的执行脚本的初始化工作,Particle
System组件肯定也是个脚本,虽然我们看不到它实现的方式,但是Instantiate以后它定会先执行Awake()和OnEnable()一类初始化的方法。

那对象池的原理到底是什么呢,就是在我们创建出来物体后,当需要删除的时候并不是将它Destroy掉,而是将它SetActive(false);只是在场景中不显示并把它添加到字典或列表中,以备下次使用时不是去Instantiate(),而是从字典或列表中取出这个物体并对它的信息进行重置(包括SetActive(true))。我想在这个时候大家就明白了对象池的原理了,也没有大家想象中的那么难。

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

public class ObjectPool : MonoBehaviour {

    //单例模式

    public static ObjectPool Instance;

    //创建一个字典key为string类型,value为ArrayList类型

    private Dictionary<string, ArrayList> pool = new Dictionary<string, ArrayList>();
// Use this for initialization
void Start () {

        Instance = this;
}

    //根据形参来获取到我们需要的物体
public Object GetPool_Obj(string prefabName,Vector3 pos,Quaternion rot)

    {

        //在这有我才有Resources.Load()加载方式,所以预制物体要放在Resources文件夹下,在创建后名字后面都被加了一个Clone;

        string key = prefabName + "(Clone)";

        Object obj;

        //根据key判断字典里有没有这个物体,如果有则取出来,然后重置,否则就创建一个

        if(pool.ContainsKey(key)&&pool[key].Count>0)

        {

            ArrayList list = pool[key];

            obj = list[0] as Object;

            list.RemoveAt(0);

            (obj as GameObject).SetActive(true);

            (obj as GameObject).transform.position = pos;

            (obj as GameObject).transform.rotation = rot;

        }

        else

        {

            obj = Instantiate(Resources.Load(prefabName), pos, rot);

        }

        //下面2行就是在被创建出来的物体上所绑定的脚本,用来调用ReturnPool_Obj();

        DelayDestroy delay = (obj as GameObject).GetComponent<DelayDestroy>();

        delay.Init();

        return obj;

    }

    //将物体添加到字典中

    public Object ReturnPool_Obj(GameObject obj)

    {

        string key = obj.name;

        if(pool.ContainsKey(key))

        {

            ArrayList list = pool[key];

            list.Add(obj);

        }

        else

        {

            pool[key] = new ArrayList { obj};

        }

        obj.SetActive(false);

        return obj;

    }

}

上面的cs就是对象池脚本,下面的是创建物体上绑定的脚本中对ReturnPool_Obj()调用。

 public void Init()

    {

        StartCoroutine(ReturnToPool());

    }

    IEnumerator ReturnToPool()

    {

        yield return new WaitForSeconds(2);

        ObjectPool.Instance.ReturnPool_Obj(this.gameObject);

    }

当然你可以根据项目的需要而自己设定,我这里是用协同的方法在2s后调用。

好了,对于对象池的理解我也只是小猪,谢谢大家!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: