Unity3D仿星露谷物语开发41之创建池管理器
1、目标
在PersistentScene中创建池管理器(Pool Manager)。这将允许一个预制对象池被创建和重用。
在游戏中当鼠标点击地面时,便会启用某一个对象。比如点击地面,就创建了一棵树,而这棵树是从预制体对象池中获取的(并且最大数量有限)。
2、池管理器
(1)概念
对象池通常用于频繁或快速生成的游戏对象,如游戏中的子弹。
什么是池管理器,以及它们为什么有用?
- 对象池是指在场景中有一组“池化”对象,在需要时可以启用它们,不需要时可以禁用它们。
- 这避免了创建新对象和销毁不再需要的对象
- 反复创建新对象和销毁旧对象会消耗大量资源,并引发问题,例如增加“垃圾”回收量。当系统试图清理反复分配的未使用内存时,这可能会在游戏运行中导致掉帧。
- 通过使用“池”中的对象,并在不再需要时将其返回池中,可以减少这些性能问题。
(2)创建流程
(3)使用池对象
3、创建PoolManager.cs脚本
在Assets -> Scripts 下新建目录命名为VFX,在此目录下创建新脚本命名为PoolManager。
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PoolManager : SingletonMonobehaviour<PoolManager>
{private Dictionary<int, Queue<GameObject>> poolDictionary = new Dictionary<int, Queue<GameObject>>();[SerializeField] private Pool[] pool = null; // 池数组,每个值为预制体和个数。[SerializeField] private Transform objectPoolTransform = null; // 用于存储对象池的父 Transform [System.Serializable]public struct Pool{public int poolSize;public GameObject prefab;}private void Start(){// Create object pools on startfor(int i = 0; i < pool.Length; i++){CreatePool(pool[i].prefab, pool[i].poolSize);}}private void CreatePool(GameObject prefab, int poolSize){int poolKey = prefab.GetInstanceID();string prefabName = prefab.name; // get prefab nameGameObject parentGameObject = new GameObject(prefabName + "Anchor"); // 创建一个新的游戏对象作为该对象池所有游戏对象的父对象,并将其设置为objectPoolTransform的子对象。parentGameObject.transform.SetParent(objectPoolTransform);if (!poolDictionary.ContainsKey(poolKey)){poolDictionary.Add(poolKey, new Queue<GameObject>());for(int i = 0; i < poolSize; i++){GameObject newObject = Instantiate(prefab, parentGameObject.transform) as GameObject;newObject.SetActive(false);poolDictionary[poolKey].Enqueue( newObject );}}}public GameObject ReuseObject(GameObject prefab, Vector3 position, Quaternion rotation){int poolKey = prefab.GetInstanceID() ;if (poolDictionary.ContainsKey(poolKey)){// Get object from pool queueGameObject objectToReuse = GetObjectFromPool(poolKey);ResetObject(position, rotation, objectToReuse, prefab);return objectToReuse;}else{Debug.Log("No object pool for " + prefab);return null;}}private GameObject GetObjectFromPool(int poolKey){GameObject objectToReuse = poolDictionary[poolKey].Dequeue();poolDictionary[poolKey].Enqueue(objectToReuse);// log to console if object is currently activeif(objectToReuse.activeSelf == true) // objectToReuse.activeSelf 是 GameObject 类的一个属性,用于检查该对象当前是否处于激活状态。{objectToReuse.SetActive(false); // 确保返回的对象处于非激活状态,以便后续可以根据需要重新激活使用。}return objectToReuse;}private static void ResetObject(Vector3 position, Quaternion rotation, GameObject objectToReuse, GameObject prefab){objectToReuse.transform.position = position;objectToReuse.transform.rotation = rotation;objectToReuse.transform.localScale = prefab.transform.localScale;}
}
4、创建池对象
在Hierarchy -> PersistentScene下创建空物体命名为PoolManager。
给PoolManager对象添加PoolManager组件,设置Pool为1,同时将Transform组件拖到Object Pool Transform中。
然后,在Assets -> Prefabs -> Scenary中,复制CanyonOakScenary预制体并且命名为TestObjectPoolCanyonOak。在Element0中,设置Pool Size为20,再把TestObjectPoolCanyonOak拖入到Prefab选项中。
点击TestObjectPoolCanyonOak预制体,删除它和Trunk的Obscuringxxx组件。
5、修改Player.cs脚本
实现测试功能:当鼠标右击时,启用一个Pool中的预制体。
在最开始的变量定义中添加代码:
public GameObject canyonOakTreePrefab;
在PlayerTestInput函数中添加如下功能:
// Test object pool
if (Input.GetMouseButtonDown(1))
{GameObject tree = PoolManager.Instance.ReuseObject(canyonOakTreePrefab, mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y, -mainCamera.transform.position.z)), Quaternion.identity);tree.SetActive(true);
}
在Unity中,配置Player脚本的canyonOakTreePrefab信息。
注解:此时配置canyonOakTreePrefab信息,主要是通过int poolKey = prefab.GetInstanceID() ;获取poolKey信息,然后从Pool池中获取对象。
6、运行游戏
每次右击鼠标时,都会产生一棵树,同时最多只有20棵树(这些树会被重复利用)。
相关文章:

Unity3D仿星露谷物语开发41之创建池管理器
1、目标 在PersistentScene中创建池管理器(Pool Manager)。这将允许一个预制对象池被创建和重用。 在游戏中当鼠标点击地面时,便会启用某一个对象。比如点击地面,就创建了一棵树,而这棵树是从预制体对象池中获取的&a…...

Modbus协议介绍
Modbus是一种串行通信协议,由Modicon公司(现为施耐德电气)在1979年为可编程逻辑控制器(PLC)通信而开发。它是工业自动化领域最常用的通信协议之一,具有开放性、简单性和跨平台兼容性,广泛应用于…...
深度学习遇到的问题处理
小土堆课程学习 1.tensorboard远程到本地无法显示 1.检查本地与远程端口是否被占用 2.一定要在远程服务器的项目下创建对应的存储文件夹 且 远程服务器一定要有需要处理的数据 ## 此时远程项目路径下有logs文件夹 存放上传的图像与数据 writerSummaryWriter("logs"…...

I/O多路复用(select/poll/epoll)
通过一个进程来维护多个Socket,也就是I/O多路复用,是一种常见的并发编程技术,它允许单个线程或进程同时监视多个输入/输出(I/O)流(例如网络连接、文件描述符)。当任何一个I/O流准备好进行读写操…...

Westlake-Omni 情感端音频生成式输出模型
简述 github地址在 GitHub - xinchen-ai/Westlake-OmniContribute to xinchen-ai/Westlake-Omni development by creating an account on GitHub.https://github.com/xinchen-ai/Westlake-Omni Westlake-Omni 是由西湖心辰(xinchen-ai)开发的一个开源…...
Egg.js知识框架
一、Egg.js 核心概念 1. Egg.js 简介 基于 Koa 的企业级 Node.js 框架(阿里开源) 约定优于配置(Convention over Configuration) 插件化架构,内置多进程管理、日志、安全等能力 适合中大型企业应用,提供…...

随手记录5
一些顶级思维: 顶级思维 1、永远不要自卑。 也永远不要感觉自己比别人差,这个人有没有钱,有多少钱,其实跟你都没有关系。有很多人就是那个奴性太强,看到比自己优秀的人,甚至一些装逼的人,这…...

Linux驱动:驱动编译流程了解
要求 1、开发板中的linux的zImage必须是自己编译的 2、内核源码树,其实就是一个经过了配置编译之后的内核源码。 3、nfs挂载的rootfs,主机ubuntu中必须搭建一个nfs服务器。 内核源码树 解压 tar -jxvf x210kernel.tar.bz2 编译 make x210ii_qt_defconfigmakeCan’t use ‘…...

使用 Flowise 构建基于私有知识库的智能客服 Agent(图文教程)
使用 Flowise 构建基于私有知识库的智能客服 Agent(图文教程) 在构建 AI 客服时,常见的需求是让机器人基于企业自身的知识文档,提供准确可靠的答案。本文将手把手教你如何使用 Flowise + 向量数据库(如 Pinecone),构建一个结合 RAG(Retrieval-Augmented Generation)检…...

RabbitMQ ③-Spring使用RabbitMQ
Spring使用RabbitMQ 创建 Spring 项目后,引入依赖: <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-amqp --> <dependency><groupId>org.springframework.boot</groupId><artifac…...
测试文章标题01
模型上下文协议(Model Context Protocol, MCP)深度解析 一、MCP的核心概念 模型上下文协议(Model Context Protocol, MCP)是一种用于规范机器学习模型与外部环境交互的标准化框架。其核心目标是通过定义统一的接口和数据格式&am…...

linux中常用的命令(四)
目录 1-cat查看文件内容 2-more命令 3-less命令 4-head命令 5-tail命令 1-cat查看文件内容 cat中的一些操作 -b : 列出行号(不含空白行)-E : 将结尾的断行以 $ 的形式展示出来-n : 列出行号(含空白行)-T : 将 tab 键 以 ^I 显示…...
2025年阿里云大数据ACP高级工程师认证模拟试题(附答案解析)
这篇文章的内容是阿里云大数据ACP高级工程师认证考试的模拟试题。 所有模拟试题由AI自动生成,主要为了练习和巩固知识,并非所谓的 “题库”,考试中如果出现同样试题那真是纯属巧合。 1、下列关于MaxCompute的描述中,错误的是&am…...
【FAQ】HarmonyOS SDK 闭源开放能力 — PDF Kit
1.问题描述: 预览PDF文件,文档上所描述的loadDocument接口,可以返回文件的状态,并无法实现PDF的预览,是否有能预览PDF相关接口? 解决方案: 1、执行loadDocument进行加载PDF文件后,…...
二元随机响应(Binary Randomized Response, RR)的翻转概率
随机响应(Randomized Response)机制 ✅ 回答核心: p 1 1 e ε 才是「翻转概率」 \boxed{p \frac{1}{1 e^{\varepsilon}}} \quad \text{才是「翻转概率」} p1eε1才是「翻转概率」 而: q e ε 1 e ε 是「保留真实值」…...
hive两个表不同数据类型字段关联引发的数据倾斜
不同数据类型引发的Hive数据倾斜解决方案 #### 一、原因分析 当两个表的关联字段存在数据类型不一致时(如int vs string、bigint vs decimal),Hive会触发隐式类型转换引发以下问题: Key值的精度损失:若关联字…...

利用SSRF击穿内网!kali靶机实验
目录 1. 靶场拓扑图 2. 判断SSRF的存在 3. SSRF获取本地信息 3.1. SSRF常用协议 3.2. 使用file协议 4. 172.150.23.1/24探测端口 5. 172.150.23.22 - 代码注入 6. 172.150.23.23 SQL注入 7. 172.150.23.24 命令执行 7.1. 实验步骤 8. 172.150.23.27:6379 Redis未授权…...

DVWA在线靶场-xss部分
目录 1. xxs(dom) 1.1 low 1.2 medium 1.3 high 1.4 impossible 2. xss(reflected) 反射型 2.1 low 2.2 medium 2.3 high 2.4 impossible 3. xss(stored)存储型 --留言板 3.1 low 3.2 medium 3.3 high 3.…...

Go 语言 slice(切片) 的使用
序言 在许多开发语言中,动态数组是必不可少的一个组成部分。在实际的开发中很少会使用到数组,因为对于数组的大小大多数情况下我们是不能事先就确定好的,所以他不够灵活。动态数组通过提供自动扩容的机制,极大地提升了开发效率。这…...
Android Exoplayer 实现多个音视频文件混合播放以及音轨切换
在之前的文章ExoPlayer中常见MediaSource子类的区别和使用场景中介绍了Exoplayer中各种子MediaSource的使用场景,这篇我们着重详细介绍下实现多路流混合播放的用法。常见的使用场景有:视频文件电影字幕、正片视频广告视频、背景视频背景音乐等。 初始化…...
深入浅出:Java 中的动态类加载与编译技术
1. 引言 Java 的动态性是其强大功能之一,允许开发者在运行时加载和编译类,从而构建灵活、可扩展的应用程序。动态类加载和编译在许多高级场景中至关重要,例如插件系统、动态代理、框架开发(如 Spring)和代码生成工具。Java 提供了两大核心机制来实现这一目标: 自定义 Cl…...

js常用的数组遍历方式
以下是一个完整的示例,将包含图片、文字和数字的数组渲染到 HTML 页面,使用 多种遍历方式 实现不同的渲染效果: 1. 准备数据(数组) const items [{ id: 1, name: "苹果", price: 5.99, image: "h…...

【网络编程】五、三次握手 四次挥手
文章目录 Ⅰ. 三次握手Ⅱ. 建立连接后的通信Ⅲ. 四次挥手 Ⅰ. 三次握手 1、首先双方都是处于未通信的状态,也就是关闭状态 CLOSE。 2、因为服务端是为了服务客户端的,所以它会提前调用 listen() 函数进行对客户端请求的监听。 3、接着客户端就…...
【类拷贝文件的运用】
常用示例 当我们面临将文本文件分成最大大小块的时,我们可能会尝试编写如下代码: public class TestSplit {private static final long maxFileSizeBytes 10 * 1024 * 1024; // 默认10MBpublic void split(Path inputFile, Path outputDir) throws IOException {…...

从 AGI 到具身智能体:解构 AI 核心概念与演化路径全景20250509
🤖 从 AGI 到具身智能体:解构 AI 核心概念与演化路径全景 作者:AI 应用实践者 在过去的几年中,AI 领域飞速发展,从简单的文本生成模型演进为今天具备复杂推理、感知能力的“智能体”系统。本文将从核心概念出发&#x…...

Docker Compose 的历史和发展
这张图表展示了Docker Compose从V1到V2的演变过程,并解释了不同版本的Compose文件格式及其支持情况。以下是对图表的详细讲解: Compose V1 No longer supported: Compose V1已经不再支持。Compose file format 3.x: 使用了版本3.x的Compose文件格式。 …...
ARMV8 RK3399 u-boot TPL启动流程分析 --crt0.S
上一篇介绍到start.S 最后一个指令是跳转到_main, 接下来分析 __main 都做了什么 arch/arm/lib/crt0.S __main 注释写的很详细,主要分为5步 1. 准备board_init_f的运行环境 2. 跳转到board_init_f 3. 设置broad_init_f 申请的stack 和 GD 4. 完整u-boot 执行re…...

从 JIT 即时编译一直讲到CGI|FastGGI|WSGI|ASGI四种协议的实现细节
背景 我一度理解错了这个东西,之前没有AI的时候,也没深究过,还觉得PHP8支持了常驻内存的运行的错误理解,时至今日再来看这个就很清晰了。 另外,早几年对以上4个协议,我也没搞懂,时至今日&…...
Vue.js 页面切换空白与刷新 404 问题深度解析
在使用 Vue.js 开发单页应用 (SPA) 的过程中,开发者经常会遇到两个常见问题:页面切换时出现短暂的空白屏幕,以及刷新页面时返回 404 错误。这两个问题不仅影响用户体验,还可能阻碍项目的正常上线。本文将深入探讨这两个问题的成因…...

CSS3 遮罩
在网页设计中,我们经常需要实现一些特殊的视觉效果来增强用户体验。CSS3 遮罩(mask)允许我们通过控制元素的可见区域来创建各种精美的视觉效果。本文将带你全面了解 CSS3 遮罩的功能和应用。 什么是 CSS3 遮罩? CSS3 遮罩是一种…...