对象池的使用及理解

使用对象池之前的需求:
对象池真的是一种优化手段吗,它并不是适用大多情况,并且使用不当的话,反而得到相反的情况,内存和CPU反而消耗更大。
首先明确下对象池是什么?
对象池就是大量对象的集合,将它们都存入链表中。
对象池有什么作用?
当一定量的同类对象需要频繁的出现又消失时,为了避免频繁创建对象而造成效率低下,把符合消失条件的对象先不移除,等待下次使用时回收。

下面介绍一下对象池。1:对象池一般有会两个链表。一个是idle链表,一个是busy链表(就是创建一个类,里面有两个链表)。2:对外的接口一般有取出对象和回收对象两个。3:当你调用取出接口的时候,对象池会从idle里面拿出来一个返回给你并且把这个对象从idle里面删除掉添加到busy里。如果对象池发现idle是空的,对象池就会创建一个对象。然后把对象反给你并且把对象添加到busy里。4:当你调用回收接口的时候(注意把你要回收的对象传进去),对象池会把要回收的对象放到idle里并且从busy里移除掉。怎么样是不是很简单!

下面看一下实例!
在这里插入图片描述
代码:
首先创建一个对象池,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//对象池管理
public class ObjectPoolManager : MonoBehaviour {
//单列
public static ObjectPoolManager instance;
void Awake ()
{
instance = this;
}
private Dictionary<string, List> pool;
void Start () {
pool = new Dictionary<string, List>();
}
///
/// 取对象的方法
/// 预设体的名字池子的名字键值对的键名
/// 生成对象的坐标
/// 生成对象的角度
/// 得到的对象

//取对象的方法
public GameObject GetObjectFormPool(string objName,Vector3 pos ,Quaternion qua) 
{
    GameObject go;
    
    //判断是否存在对应的池子(通过字典的键值对判断是否包含objname的键)
    //,并判断池子里是否包含对象,有对象才能取出来(通过判断list里元素的个数,大于0则说明至少有一个)
    if (pool.ContainsKey(objName) && pool[objName].Count > 0)
    {
        //从链表中取出第0个元素
        go = pool[objName][0];
        //并将第0个元素从链表中移除
        pool[objName].RemoveAt(0);
        //激活取出的对象
        go.SetActive(true);
    }
    else
    {
        //加载预设体
        go =Instantiate(Resources.Load(objName) as GameObject);
    }
    //赋值坐标
    go.transform.position = pos;
    //赋值角度
    go.transform.rotation = qua;

    return go;
}

//存对象的方法
public void PushObjectToPool (GameObject go)
{
    //通过Instantiate生成的对象名字均为预设体名字加上(clone),所以需要切割
    //才能得到真正预设体的名字

    string prefabName = go.name.Split('(')[0];

    //通过预设体的名字来判断是否已经有对应的池子,如果有直接将go放到池子中
    if (pool.ContainsKey(prefabName))
    {
        pool[prefabName].Add(go);   
    }   
    //没有对应的池子,那就在pool中创建一租键值对,并将go放到新池子中
    else
    {
        //创建键值对
        pool[prefabName] = new List<GameObject>() {go};
    }

    //刚开始存入池子的 对象清零
    go.GetComponent<Rigidbody>().velocity= Vector3.zero;

    go.SetActive(false);
}

}

第二篇代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//脚本任意挂入一个object对象中
public class ObjectPool : MonoBehaviour {
const string redBullet = “Red”;
const string YellowBullet = “Yellow”;

//生成红色子弹的预设体
public GameObject redBulletPrefab;

public GameObject YellowBulletPrefab;

//红色子弹生成的位置
public Transform redBulletPos;

public Transform yellowBulletPos;
// Use this for initialization
void Start () {
	
}

// Update is called once per frame
void Update () {
    
    if (Input.GetMouseButtonDown(0))
    {
        GameObject go = ObjectPoolManager.instance.GetObjectFormPool(redBullet, redBulletPos.position, redBulletPos.rotation);
        go.GetComponent<Rigidbody>().AddForce(go.transform .forward*500);
        StartCoroutine(DestoryBullect(go));
    }
    if (Input.GetMouseButtonDown(1))
    {
  GameObject go = ObjectPoolManager.instance.GetObjectFormPool(YellowBullet, yellowBulletPos.position, yellowBulletPos.rotation);
        go.GetComponent<Rigidbody>().AddForce(go.transform.forward * 500);
        StartCoroutine(DestoryBullect(go));
    }
}
/// <summary>
/// 使用协程调用让子弹在激活后1秒自动“销毁”(进入不激活状态)
/// </summary>
/// <param name="go"></param>
/// <returns></returns>
IEnumerator DestoryBullect (GameObject go)
{
    yield return new WaitForSeconds(1);
    go.GetComponent<Rigidbody>().velocity = Vector3.zero;
    ObjectPoolManager.instance.PushObjectToPool(go);
}

}

这样就好啦!下次见!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值