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.mzph.cn/pingmian/71284.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github 2025-03-03 开源项目周报Top14

根据Github Trendings的统计,本周(2025-03-03统计)共有14个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目5TypeScript项目4Jupyter Notebook项目3Go项目2JavaScript项目2C++项目2Vue项目1Rust项目1Dify.AI: 开源的LLM应用程序开发平台 创建…

spark 虚拟机基本命令(2)

cp 命令&#xff0c;复制 格式&#xff1a;cp 源文件 目标文件 cp -r 命令 复制目录 格式&#xff1a;cp -r 源文件 目标文件夹 mv 命令&#xff0c;重命名和移动 格式&#xff1a;mv 源文件 目标文件 说明&#xff1a;若源文件和目标文件在同一个目录下&#xff0c;就是重命…

阿里管理三板斧课程和管理工具包(视频精讲+工具文档).zip

阿里管理三板斧课程和管理工具包&#xff08;视频精讲工具文档&#xff09;&#xff0c;共18课。 阿里管理三板斧工具包 阿里绩效考核文档 阿里人力资源实践全集文档 阿里文化构建工具包 阿里正委体系工具包 阿里三板斧.pdf 阿里三板斧-学员手册.pdf 第1集 三板斧的底层逻辑.…

Java RPC(远程过程调用)技术详解

在当今分布式系统盛行的时代&#xff0c;服务间的通信变得至关重要。Java RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;作为一种高效、透明的远程通信手段&#xff0c;在微服务架构、分布式计算等领域扮演着重要角色。本文将深入介绍Java RPC的基…

Java【多线程】(2)线程属性与线程安全

目录 1.前言 2.正文 2.1线程的进阶实现 2.2线程的核心属性 2.3线程安全 2.3.1线程安全问题的原因 2.3.2加锁和互斥 2.3.3可重入&#xff08;如何自己实现可重入锁&#xff09; 2.4.4死锁&#xff08;三种情况&#xff09; 2.4.4.1第一种情况 2.4.4.2第二种情况 2.4…

深入解析Java虚拟机(JVM)的核心组成

深入解析Java虚拟机&#xff08;JVM&#xff09;的核心组成 Java虚拟机&#xff08;JVM&#xff09;作为Java语言跨平台的核心实现&#xff0c;其架构设计精妙而复杂。理解JVM的组成部分&#xff0c;是掌握Java内存管理、性能调优和问题排查的关键。本文将从四大核心模块剖析J…

16.8 LangChain RAG 实战指南:构建知识驱动的智能问答系统

LangChain RAG 实战指南:构建知识驱动的智能问答系统 关键词:RAG 实现、向量检索优化、多源知识融合、LCEL 链式编排、生产级知识库 1. RAG 核心架构解析 1.1 技术实现流程图 #mermaid-svg-8Xfi8BXbIrAXc35l {font-family:"trebuchet ms",verdana,arial,sans-ser…

DeepSeek如何快速开发PDF转Word软件

一、引言 如今&#xff0c;在线工具的普及让PDF转Word成为了一个常见需求&#xff0c;常见的PDF转Word工具有收费的WPS&#xff0c;免费的有PDFGear&#xff0c;以及在线工具SmallPDF、iLovePDF、24PDF等。然而&#xff0c;大多数免费在线转换工具存在严重隐私风险——文件需上…

[KEIL]单片机技巧 01

1、查看外设寄存器的值 配合对应的芯片开发手册以查看寄存器及其每一位的意义&#xff0c;可以解决90%以上的单纯的片内外设bug&#xff0c;学会如何通过寄存器的值来排外设上的蛊是嵌入式开发从小白到入门的重要一步&#xff0c;一定要善于使用这个工具&#xff0c;而不是外设…

Redis详解(实战 + 面试)

目录 Redis 是单线程的&#xff01;为什么 Redis-Key(操作redis的key命令) String 扩展字符串操作命令 数字增长命令 字符串范围range命令 设置过期时间命令 批量设置值 string设置对象,但最好使用hash来存储对象 组合命令getset,先get然后在set Hash hash命令: h…

计算机视觉(opencv-python)入门之图像的读取,显示,与保存

在计算机视觉领域&#xff0c;Python的cv2库是一个不可或缺的工具&#xff0c;它提供了丰富的图像处理功能。作为OpenCV的Python接口&#xff0c;cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV 图像格式 BMP格式 …

【SpringBoot】【log】 自定义logback日志配置

前言&#xff1a;默认情况下&#xff0c;SpringBoot内部使用logback作为系统日志实现的框架&#xff0c;将日志输出到控制台&#xff0c;不会写到日志文件。如果在application.properties或application.yml配置&#xff0c;这样只能配置简单的场景&#xff0c;保存路径、日志格…

【开源-线程池(Thread Pool)项目对比】

一些实现**线程池&#xff08;Thread Pool&#xff09;**功能的开源项目的对比分析。 线程池功能的开源项目 项目名称语言优点缺点适用场景开源代码链接ThreadPoolC简单易用&#xff0c;代码简洁&#xff1b;适合快速原型开发。功能较为基础&#xff0c;不支持动态调整线程数…

Hive之正则表达式RLIKE详解及示例

目录 一、RLIKE 语法及核心特性 1. 基本语法 2. 核心特性 二、常见业务场景及示例 场景1&#xff1a;过滤包含特定模式的日志&#xff08;如错误日志&#xff09; 场景2&#xff1a;验证字段格式&#xff08;如邮箱、手机号&#xff09; 场景3&#xff1a;提取复杂文本中…

在Docker中部署DataKit最佳实践

本文主要介绍如何在 Docker 中安装 DataKit。 配置和启动 DataKit 容器 登陆观测云平台&#xff0c;点击「集成」 -「DataKit」 - 「Docker」&#xff0c;然后拷贝第二步的启动命令&#xff0c;启动参数按实际情况配置。 拷贝启动命令&#xff1a; sudo docker run \--hostn…

Mac OS Homebrew更换国内镜像源(中科大;阿里;清华)

omebrew官方的源一般下载包之类的会很慢&#xff0c;所以通常我们都是用国内的镜像源来代替&#xff0c;这样会提高我们的效率。Homebrew主要有四个部分组成: brew、homebrew-core 、homebrew-bottles、homebrew-cask。 代码语言&#xff1a;javascript 代码运行次数&#xf…

React Native 原理

React Native 是一个跨平台移动应用开发框架&#xff0c;它允许开发者使用 JavaScript 和 React 来开发 iOS 和 Android 原生应用。React Native 的核心原理是通过 桥接&#xff08;Bridge&#xff09; 技术&#xff0c;使用 JavaScript 来控制原生组件&#xff0c;并将应用逻辑…

实验:k8s+keepalived+nginx+iptables

1、创建两个nginx的pod&#xff0c;app都是nginx nginx1 nginx2 2、创建两个的pod的service 3、配置两台keepalived的调度器和nginx七层反向代理&#xff0c;VIP设置192.168.254.110 keepalived调度器master keepalived调度器backup 两台调度器都配置nginx七层反向代理&#…

火山引擎 DeepSeek R1 API 使用小白教程

一、火山引擎 DeepSeek R1 API 申请 首先需要三个要素&#xff1a; 1&#xff09;API Key 2&#xff09;API 地址 3&#xff09;模型ID 1、首先打开火山引擎的 DeepSeek R1 模型页面 地址&#xff1a;账号登录-火山引擎 2、在页面右下角&#xff0c;找到【推理】按钮&#…

Pytorch使用手册--将 PyTorch 模型导出为 ONNX(专题二十六)

注意 截至 PyTorch 2.1,ONNX 导出器有两个版本。 torch.onnx.dynamo_export 是最新的(仍处于测试阶段)导出器,基于 PyTorch 2.0 发布的 TorchDynamo 技术。 torch.onnx.export 基于 TorchScript 后端,自 PyTorch 1.2.0 起可用。 一、torch.onnx.dynamo_export使用 在 60 …