Unity中对象池的使用

Unity中性能优化最重要的一个方法就是使用对象池。对象池是为了避免物体重复的创建与销毁。如果有一个物体的使用频率很高比如说:子弹就会重复的创建与销毁。那么就可以在子弹销毁的时候可以把他存在池子中并把物体隐藏(不销毁),下次再使用这个物体的时候直接从池子中取出来就可以了(显示),这样就避免了物体的重复创建与销毁,实现了物体的复用。

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

/// <summary>
/// 对象池管理
/// </summary>
/// !!!此脚本写好后基本上不需要改动脚本,使用此脚本时需要把此脚本挂在场景中,否则无法使用此脚本
public class ObjectPoolManager : MonoBehaviour

{   //单例
    public static ObjectPoolManager instance;

    //Dictionary字典
    //创建字典,键为string类型,值为List类型的,字典的名字为pool
    private Dictionary<string, List<GameObject>> pool;


    private void Awake()
    {
        instance = this;
    }

    void Start()
    {
        //实例化字典
        pool = new Dictionary<string, List<GameObject>>();
    }

    /// <summary>
    /// 取对象的方法
    /// </summary>
    /// <param name="objName">预设体的名字,也是池子里的名字,也是键值对的名字</param>
    /// <param name="pos">生成对象的坐标</param>
    /// <param name="qua">生成对象的角度</param>
    /// <returns>得到的对象</returns> GameObject为返回值 返回的是实例化的对象
    public GameObject GetObjectFormPool(string objName,Vector3 pos,Quaternion qua)
    {
        //被实例化的对象
        GameObject go;

        //判断是否存在对应的池子(通过字典的键值对判断是否包含objname的键)
        //并判断池子里是否包含对象,有对象才能取出来(通过判断List里的元素个数,大于0说明至少有一个)
        if (pool.ContainsKey(objName) && pool[objName].Count > 0)
        {
            //从链表中取出地一个元素
            go = pool[objName][0];

            //并将地0个元素从链表中移除
            pool[objName].RemoveAt(0);

            //激活取出的对象                          
            go.SetActive(true);

        }

        else
        {
            //如果池子中没有该元素,就从Resources文件夹中实例化出来赋值给go
            go = Instantiate(Resources.Load(objName) as GameObject);
        }

        //赋值坐标      
        go.transform.position = pos;

        //赋值角度
        go.transform.rotation = qua;

        //把生成的预设体返回给go
        return go;
    }


   






 //把实例化出来的物体都存到池子中
    public void PushObjectToPool(GameObject go)
    {
        //通过Instantiate生成的对象名字均为预设体名字加上(clone),所以需要
        //切割才能得到真正预设体的名字
        string prefabName = go.name.Split('(')[0];

        //通过预设体的名字来判断是否已经有对应的池子,如果有直接将go放到池子中
        if (pool.ContainsKey(prefabName))
        {
            //把对象go添加到池子中
            pool[prefabName].Add(go);
        }

        //没有对应的池子,那就在pool中创建一组键值对,并将go放到新的池子中
        else
        {
            //实例化一个池子并把go放到池子中
            pool[prefabName] = new List<GameObject>() { go };
            
        }

        //把物体放到池子中后要把物体身上的速度设为0
        go.GetComponent<Rigidbody>().velocity = Vector3.zero;

        //把预设体放入池子中后要把生成出来的物体设为隐藏状态
        go.SetActive(false);
    }


}

一个从池子中取物体的方法,一个把物体存在池子中的方法。当使用对象池的时候调用这两个方法就可以了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值