Unity对象池应用

对象池,顾名思义,就是放对象的池子。
优缺点:空间换时间,用额外的内存消耗减少创建物体的时间,保证运行的流畅度。
何时用:当需要大量创建相同游戏物体时,例如射击游戏中不停的创建子弹销毁子弹。大量地创建物体销毁物体会造成游戏卡顿,为了解决这个方法可以采用对象池。

实现
1、需要一个容器,用来实现存放对象
2、一个取对象的方法
3、一个存对象的方法
详细代码如下:
关键地方已写了详细备注。

public class GameObjectPool : MonoBehaviour {

    private static GameObjectPool instance;
    public static GameObjectPool Instance
    {
        get
        {
            if (instance == null)
            {
                GameObject obj = new GameObject("GameObjectPool");
                instance = obj.AddComponent<GameObjectPool>();
                DontDestroyOnLoad(obj);
            }
            return instance;
        }
    }
    //对象池
    public Dictionary<string, List<GameObject>> cache;

    public GameObject GetGameObject(string key, GameObject prefab, Vector3 position)
    {
        GameObject obj;
        //如果字典中存在当前键,并且当前键的对象池里有未使用的游戏物体,则直接拿出一个使用。
        if (cache.ContainsKey(key) && cache[key].Where(w => w.activeSelf == false).Count() > 0)
        {
            obj = cache[key][0];
            cache[key].RemoveAt(0);
        }
        //如果字典中存在当前键,但是当前键的对象池物体已经被用完,则根据传进来的预制体新创建一个。
        else if (cache.ContainsKey(key) && cache[key].Where(w => w.activeSelf == false).Count() <= 0)
        {
            obj = Instantiate(prefab) as GameObject;
        }
        //字典中不存在当前键,新建一个键与相对应的对象池,并根据传进来的预制体新创建一个
        else
        {
            obj = Instantiate(prefab) as GameObject;
            cache.Add(key, new List<GameObject>());
        }
        obj.SetActive(true);
        obj.transform.position = position;
        obj.transform.SetParent(transform);
        return obj;
    }
    //延迟回收
    public void CollectObject(string key,GameObject obj)
    {
        StartCoroutine(DelayCollect(key, obj));
    }
    //回收对象池的方法,将物体放回对象池并且设置为false
    IEnumerator DelayCollect(string key,GameObject obj)
    {
        cache[key].Add(obj);
        yield return new WaitForSeconds(2);
        obj.SetActive(false);
    }
    //清空对象池中没有使用的对象
    public void Clear(string key)
    {
        if (cache.ContainsKey(key))
        {
            //Destroy当中所有的对象
            for (int i = 0; i < cache[key].Where(w => w.activeSelf == false).Count(); i++)
            {
                Destroy(cache[key][i]);
            }
            if (cache[key].Where(w => w.activeSelf == true).Count() <= 0)
                cache.Remove(key);
        }
    }
    public void AllClear()
    {
        var list = new List<string>(cache.Keys);
        for (int i = 0; i < list.Count; i++)
        {
            Clear(list[i]);
        }
    }
    private void Awake()
    {
        cache = new Dictionary<string, List<GameObject>>();
    }
}

对象池测试脚本代码如下:

public class PoolTest : MonoBehaviour {

    GameObject prefabCube;

    GameObject prefabSphere;

    GameObject go;
    private void Start()
    {
        Init();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            go = GameObjectPool.Instance.GetGameObject("Cube", prefabCube, new Vector3(Random.Range(-4, 4), Random.Range(-4, 4), 0));
            go.name = "Cube";
            GameObjectPool.Instance.CollectObject(go.name, go);
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            go = GameObjectPool.Instance.GetGameObject("Sphere", prefabSphere, new Vector3(Random.Range(-4, 4), Random.Range(-4, 4), 0));
            go.name = "Sphere";
            GameObjectPool.Instance.CollectObject(go.name, go);
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            GameObjectPool.Instance.AllClear();
        }

    }
    private void Init()
    {
        prefabCube = Resources.Load("Prefab/Cube") as GameObject;
        prefabSphere = Resources.Load("Prefab/Sphere") as GameObject;
    }
}

实际演示效果:
在这里插入图片描述
可以看到,当对象池有物体时并且可用数量不为0时,会直接将对象池的物体拿来用,不存在或者可用数量为0时才会新建。
ps:实现对象池的方式多种多样,什么时候回收也要根据具体的条件做适应的修改,这里只是做一个最简单的案例。
案例Demo

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值