当前位置: 首页 > article >正文

Unity 对象池技术

介绍

是什么?

在开始时初始化若干对象,将它们存到对象池中。需要使用的时候从对象池中取出,使用完后重新放回对象池中。

优点

可以避免频繁创建和销毁对象带来性能消耗。

适用场景

如果需要对某种对象进行频繁创建和销毁时,例如应用在发射子弹、多个敌人创建等

代码逻辑

Unity中实现思路

1、设定初始化数量,创建List列表作为对象池容器。

2、初始化时通过Instantiate方法根据指定数量实例化一批对象,并存入List容器中。

3、使用时从容器中取出一个可用对象并SetActive(true),取出后从容器中移除。

4、使用完毕后,将对象SetActive(false),并重新放回List容器中。

主要方法

//初始化对象池
private void InitPool()
{

}

//创建单个对象池中的对象
private GameObject CreatePoolCell()
{

}

//从对象池中取出可用对象
private GameObject GetObjectFromPool()
{

}

//将对象放回对象池中
private void BackObjectToPool(GameObject obj)
{

}

//删除对象池
private void DestroyObjectPool()
{

}

示例代码

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

public class Test : MonoBehaviour
{
    public GameObject template;
    public Transform parentRoot;
    public Transform newRoot;
    private List<GameObject> objectPool;
    private int initCount;//对象池初始化的数量
    
    void Start()
    {
        InitPool();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var obj = GetObjectFromPool();
            ResetLocalPos(obj, newRoot);
            StartCoroutine(Check1(obj));
        }
    }
    IEnumerator Check1(GameObject obj)
    {
        yield return new WaitForSeconds(5f);
        BackObjectToPool(obj);
    }

    #region 对象池逻辑
    //初始化对象池
    private void InitPool()
    {
        initCount = 10;
        objectPool = new List<GameObject>();
        for (var i = 0; i < initCount; i++)
        {
            var obj = CreatePoolCell();
            objectPool.Add(obj);
        }
    }

    //创建单个对象池中的对象
    private GameObject CreatePoolCell()
    {
        var obj = Instantiate(template, parentRoot);
        obj.SetActive(false);
        obj.transform.localPosition = Vector3.zero;
        return obj;
    }

    //从对象池中取出可用对象
    private GameObject GetObjectFromPool()
    {
        for (var i = 0; i < objectPool.Count; i++)
        {
            var obj = objectPool[i];
            if (!obj.activeInHierarchy)
            {
                obj.SetActive(true);
                objectPool.Remove(obj);
                return obj;
            }
        }
            
        var newObj = CreatePoolCell();
        newObj.SetActive(true);
        return newObj;
    }
        
    //将对象放回对象池中
    private void BackObjectToPool(GameObject obj)
    {
        if (objectPool.Contains(obj))
        {
            return;
        }
        obj.SetActive(false);
        ResetLocalPos(obj, parentRoot);
        objectPool.Add(obj);
    }
        
    //删除对象池
    private void DestroyObjectPool()
    {
        foreach (var iconObj in objectPool)
        {
            DestroyImmediate(iconObj);
        }
        objectPool.Clear();
    }

    private void ResetLocalPos(GameObject obj,Transform parent)
    {
        var trans = obj.transform;
        trans.SetParent(parent);
        trans.localPosition = Vector3.zero;
    }
    #endregion
}

Unity自带对象池

构造函数

//将会在创建新对象的时侯调用
Func<T> createFunc,    

//会在从池子获取对象的时侯调用
Action<T> actionOnGet = null,  
 
//将对象放回池子里的时侯调用
Action<T> actionOnRelease = null,  

//会在彻底销毁对象的时侯调用
Action<T> actionOnDestroy = null,  

//安全检查,防止将已经回收过的对象进行再一次的重复回收,默认参数的true即可
bool collectionCheck = true,    

//池子初始的默认大小,会在初始化时创建一个该容量大小的 stack
//需要根据自己项目的实际需求去权衡一下初始容量的大小。
int defaultCapacity = 10,

//主要是防止对象池内存过量增长,限定的对象池内最大可容纳的对象数量,
//如果池子超出了这个大小,接下来的回收对象将不会回到对象池
//而是直接调用它的 actionOnDestroy 回调进行销毁操作。
int maxSize = 10000)

主要属性和方法

接口

类型

描述

CountActive

属性

正在使用(即被激活的)的对象数量

CountInactive

属性

可以重用的对象数量

CountAll

属性

正在使用的对象和可以重用的对象的总数量

Get

方法

从对象池中获取对象

Release

方法

将对象放回池子中

Clear

方法

清理对象池

示例代码

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

public class Test : MonoBehaviour
{
    public GameObject template;
    public Transform parentRoot;
    public Transform newRoot;
    private List<GameObject> objectPool;
    private int initCount;//对象池初始化的数量
    
    private ObjectPool<GameObject> testPool;
    public bool useObjectPool;
    
    void Start()
    {
        testPool = new ObjectPool<GameObject>(() =>
        {
            //createFunc
            //将会在创建新对象的时侯调用
            var obj = Instantiate(template, parentRoot);
            obj.SetActive(false);
            obj.transform.localPosition = Vector3.zero;
            return obj;
        },
        (go) =>
        {
            // actionOnGet 
            // 会在通过池子获取对象的时侯调用,
            go.SetActive(true);
            var trans = go.transform;
            trans.SetParent(newRoot);
            trans.localPosition = Random.insideUnitSphere;
        },
        (go) =>
        {
            // actionOnRelease
            // 在对象放回池子里的时侯调用,这里我们取消激活需要放回池中的对象
            go.SetActive(false);
            var trans = go.transform;
            trans.SetParent(parentRoot);
            trans.localPosition = Vector3.zero;
        },
        (go) =>
        {
            /* actionOnDestroy 会在彻底销毁对象的时侯调用
           这里直接去destroy它就可以了
           对象池会在你手动释放对象或者内部空间无法存储你返回的对象的时侯
           调用这个函数来销毁它们
            */
            Destroy(go); 
            
        });
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var obj = testPool.Get();
            StartCoroutine(Check1(obj));
        }
    }
    IEnumerator Check1(GameObject obj)
    {
        yield return new WaitForSeconds(5f);
        testPool.Release(obj);
    }
}

其他类型的对象池


http://www.kler.cn/a/570961.html

相关文章:

  • Python 网络爬虫的应用
  • java后端开发day26--常用API(一)
  • Arduino引脚说明
  • DDK:Distilling Domain Knowledge for Efficient Large Language Models
  • AI大模型与区块链技术的结合
  • Rocky Linux 系统安装 typecho 个人博客系统(Docker 方式)
  • 通俗易懂的分类算法之朴素贝叶斯详解
  • Baklib云内容中台的核心架构是什么?
  • 【杂谈杂说】无人机行业相关国家标准及新产业应用
  • redis 与 DB 的一致性 7 种策略
  • 【华为OD机试真题29.9¥】(E卷,100分) - We Are A Team(Java Python JS C++ C )
  • ES6 特性全面解析与应用实践
  • 机器学习特征筛选:向后淘汰法原理与Python实现
  • PDF编辑器Icecream PDF Editor(免费)
  • deepseek、腾讯元宝deepseek R1、百度deepseekR1关系
  • 【GenBI 动手实战】大模型 微调LoRA SFT 实现 Text2SQL 更好的效果
  • React antd的datePicker自定义,封装成组件
  • php中使用laravel9项目 使用FFMpeg视频剪辑功能
  • ubuntu 启动不起来,光标闪烁 解决方法
  • Leetcode 刷题记录 02 —— 双指针