Unity——对象池

对象池是一种朴素的优化思想。在遇到需要大量创建和销毁同类物体的情景时,可以考虑使用对象池技术优化游戏性能。


一、为什么要使用对象池

在很多类型的游戏中都会创建和销毁大量同样类型的物体。例如,飞行射击游戏中有大量子弹,某些动作游戏中有大量敌人,还有游戏中反复出现和消失的粒子特效等。

 而创建和销毁物体本身属于比较消耗资源的操作,创建时不仅需要引擎的处理,而且还会分配大量内存,这些内存在物体销毁时还需要回收,这给虚拟机带来了垃圾回收的压力。

也就是说,场景中的物体数量较多不一定是对性能影响最大的因素。影响最大的因素有可能是一段时间内有太多物体创建和销毁。例如,在飞行射击类游戏中,每秒有许多子弹创建,稍后又有同样多的子弹因击中敌人或距离过远而销毁。而无论多麽简单的物体,在其创建和销毁的过程中都会消耗一定的资源。对象池优化所针对的正是这一类问题。

对象池技术的思想非常简答。例如,某种物体需要大量创建和销毁,那么久实现把它创建完成,放在玩家看不到的地方或隐藏起来。在需要创建的时候,直接从事先创建的物体中取出即可,而销毁的时候也不会真的销毁,只是放回了原处。这种统一管理大量物体的“池子”就叫对象池。

二、简易对象池实例 

先思考最简单的情况:一个对象池只管理同一种物体(如同一种子弹或同一种粒子)。对象池作为一个脚本组件,挂在场景中的一个空物体上以便编辑。而“池子”中的多个物体可以作为其子物体,方便管理。

对象池中的大量物体,如果用一个容器管理,则用C#队列(Queue)最合适。队列的简单实用方法如下:

  Queue<int> queue = new Queue<int>();queue.Enqueue(1);    //将数字1加入队列queue.Enqueue(2);    //将数字2加入队列queue.Enqueue(3);    //将数字3加入队列int n = queue.Dequeue();   //最早加入的数字1出队,n为1Debug.Log(queue.Count);  //获得队列长度

保存游戏物体使用Queue<GameObject>即可。用这种思路编写对象池完整代码如下,脚本名称为SimplePool

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//只存放一种数据类型物体的简单对象池
public class SimplePool : MonoBehaviour
{//私有字段加SerializeField,可以在编辑器中编辑,但其他脚本不可访问[SerializeField]private GameObject _prefab;//队列,与List类似的容器,先进先出private Queue<GameObject> _pooledInstanceQueue = new Queue<GameObject>();//通过对象池创建物体public GameObject Creat(){if (_pooledInstanceQueue.Count > 0){//如果队列中有,直接取出一个GameObject go = _pooledInstanceQueue.Dequeue();go.SetActive(true);return go;}//如果队列空了,就创建一个return Instantiatae(_prefab);}public void Destroy(GameObject go){//将不再使用的物体放回队列_pooledInstanceQueue.Enqueue(go);go.SetActive(false);//为了方便管理,所有的物体都以对象池为父物体go.transform.SetParent(gameObject.transform);}}

 三、对象池测试方法

这里我们来举例介绍

1、编写测试脚本

  1. 创建一个空物体并命名为pool,挂上之前的对象池脚本SimplePool
  2. 创建一个球体作为子弹,并挂载脚本Bullet。该脚本的用途是让子弹原理原点移动,超出一定范围则销毁自身。根据是否设置了对象池pool,决定是否通过对象池销毁。其脚本内容如下:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;public class Bullet : MonoBehaviour
    {public SimplePool pool;void Update(){//每一帧,朝远离原点的方向移动Vector3 dir = transform.position - Vector3.zero;transform.position += dir.normalized * 5.0f * Time.deltaTime;//离原点一定距离以后就销毁if (Vector3.Distance(transform.position, Vector3.zero) >= 17){//如果设置有对象池,则用对象池回收if (pool){pool.Destroy(gameObject);}else{Destroy(gameObject);}}}
    }
    
  3. 将挂在了Bullet脚本的子弹做成预制
  4. 创建一个空物体并命名为Spawner,用于生成子弹。挂载Spawner脚本,内容如下:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;public class Spawner : MonoBehaviour
    {//是否使用预制public bool usePool = true;//预制public GameObject prefab;SimplePool pool;void Start(){pool = GameObject.Find("pool").GetComponent<SimplePool>();}void Update(){if (Input.GetButtonDown("Jump")){for(int i=0;i<1000;i++)  //每次创建1000个子弹{GameObject go;if (usePool){//通过对象池创建go = pool.Creat();//对Bullet脚本组件设置pool,用于销毁go.GetComponent<Bullet>().pool = pool;}else{//通过对象池创建go = Instantiate(prefab);//不通过对象池销毁,也需要设置go.GetComponent<Bullet>().pool = null;}go.transform.position = Random.onUnitSphere * 5;go.transform.parent = transform;}}}
    }
    

  5. 确认Spawner脚本和对象池脚本都设置了子弹预制体,创建物体是会用到

2、测试方法

以上脚本可以切换是否使用对象池,主开关在Spawner脚本。Spwaner脚本有一个Use Pool选项,代表是否启用对象池。如果启用,则在子弹的创建和回收时都需要通过对象池进行;如果不启用,则使用常规的创建和销毁方法。

运行游戏,按下空格见,就可以创建大量物体了,如图:

Game窗口的右上方有一个Stats按钮,单机就可以打开一个性能统计界面,从而可以看到游戏帧率等统计信息。从统计信息中可以大致看出游戏运行时的性能表现,但对于分析对象池效果来说这些信息过于简单,不足以体现优化前后的效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/83701.shtml

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

相关文章

函数扩展之——内存函数

前言&#xff1a;小伙伴们又见面啦。 本篇文章&#xff0c;我们将讲解C语言中比较重要且常用的内存函数&#xff0c;并尝试模拟实现它们的功能。 让我们一起来学习叭。 目录 一.什么是内存函数 二.内存函数有哪些 1.memcpy &#xff08;1&#xff09;库函数memcpy &…

高云FPGA系列教程(9):cmd-parser串口命令解析器移植

文章目录 [toc]cmd-parser库简介cmd-parser库源码获取GW1NSR-4C移植cmd-parser实际测试cmd-parse命令解析器优化 本文是高云FPGA系列教程的第9篇文章。 上一篇文章介绍片上ARM Cortex-M3硬核处理器串口外设的使用&#xff0c;演示轮询方式和中断方式接收串口数据&#xff0c;并…

GLTF编辑器如何快速重置模型原点

1、什么是模型原点&#xff1f; 模型原点是三维建模中的概念&#xff0c;它是指在一个虚拟三维空间中确定的参考点。模型原点通常位于模型的几何中心或基本组件的中心位置。如图所示&#xff1a; 可以看到模型的原点在模型的几何中心 2、模型原点的作用 知道了什么是模型原点&…

ubuntu18.04安装python3.10.13

下载python包: https://www.python.org/downloads/安装关联软件包: apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev执行sudo ./configure --enable-optimizations 此命令是为了在编译 Python 时启用性…

洛谷100题DAY6

26.P1628 合并序列 法一&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1e5 10; int n, cnt; string c, s[N], a[N]; int main() {cin >> n;for(int i 1; i < n; i ){cin >> s[i];}cin >> c;int len c.size();for(int…

PHP初中高级1000道面试题大全(持续更新中50/1000)

目录 1、echo(),print(),print_r(),var_dump()的区别? 2、表单中 get与post提交方法的区别? 3、session与cookie的区别? 4、请说明 PHP 中传值与传引用的区别。什么时候传值什么时候传引用&#xff1f; 5、请解释PHP中的PDO是什么&#xff1f; 6、请解释PHP中的抽象类和…

可转债实战与案例分析——成功的和失败的可转债投资案例、教训与经验分享

实战与案例分析——投资案例研究 股票量化程序化自动交易接口 一、成功的可转债投资案例 成功的可转债投资案例提供了有价值的经验教训&#xff0c;以下是一个典型的成功案例&#xff1a; 案例&#xff1a;投资者B的成功可转债投资 投资者B是一位懂得风险管理的投资者&#…

idea如何关闭项目文件显示的浏览器图标

这里写自定义目录标题 1.idea经常项目文件右上角弹出图标2.setting中Tools 取消勾选浏览器 1.idea经常项目文件右上角弹出图标 2.setting中Tools 取消勾选浏览器

【postgresql 基础入门】表的操作,表结构查看、修改字段类型、增加删除字段、重命名表,对表的操作总是比别人棋高一着

表的操作 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献&#xff1a; toadb开源库 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子…

C语言 ,不用string.h的函数,实现A+B A-B的字符串处理功能。

请输入A串信息:abcdef 请输入B串信息:ac abcdefac B串的长度是:2 B不是A的子串&#xff0c;请重新输入B的值: ad B不是A的子串&#xff0c;请重新输入B的值: abcde A-B后的结果是:f #include <stdio.h>#define MAX 100void fun(char* a, char *b, char *c) {int ai 0;…

Zabbix

Zabbix简介 ●zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。 ●zabbix 能监视各种网络参数&#xff0c;保证服务器系统的安全运营&#xff1b;并提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题。 ●zabbix 由 2 部…

centost7下安装oracle11g 总结踩坑

1.参考文章 【总结】CentoS下Oracle静默安装流程_正在启动oracle universal installer..._仲冬二三的博客-CSDN博客 https://blog.csdn.net/Liqiong_0412/article/details/126153857? unset DISPLAY 可以跳过图形化检查 这边也卡了很久 [oraclewangmengyuan database]$ .…

创造您梦寐以求的家居设计——Live Home 3D Pro for Mac

您是否曾经想象过在舒适的家中展现自己独特的风格&#xff1f;现在&#xff0c;您可以通过Live Home 3D Pro for Mac来实现您的家居设计梦想&#xff01;这款强大的3D家居设计软件将带给您无限的创作可能性。 Live Home 3D Pro for Mac是一款专业级的家居设计软件&#xff0c;…

Visual Studio 更新:远程文件管理器

Visual Studio 中的远程文件管理器可以用来访问远程机器上的文件和文件夹&#xff0c;通过 Visual Studio 自带的连接管理器&#xff0c;可以实现不离开开发环境直接访问远程系统&#xff0c;这确实十分方便。 自从此功能发布以来&#xff0c;VS 开发团队努力工作&#xff0c;…

算法通关村-----数组中元素出现次数问题

数组中出现次数超过一半的数字 问题描述 数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个数字。你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。详见剑指offer39 问题分析 最直接的方式就是使用hashMap,遍历给定数组&#xff0c…

基于STC15单片机电子时钟液晶1602串口显示-proteus仿真-源程序

一、系统方案 1、本设计采用STC15单片机作为主控器。 2、液晶1602显示电子时钟。 3、串口显示电子时钟。 4、按键控制开启暂停清零。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 uint count0; uint8 strPhoto[8]; uint wendu0;P3M0 0x…

如何选择适合爬虫的动态住宅套餐

在当今互联网时代&#xff0c;爬虫已经成为了一项非常重要的技术。爬虫技术可以帮助企业和个人获取大量的数据&#xff0c;从而进行数据分析和决策。但是&#xff0c;要想让爬虫技术发挥最大的作用&#xff0c;就需要选择一款动态住宅套餐。那么&#xff0c;在选择动态住宅套餐…

1.3python基础语法——PyCharm

1&#xff09;PyCharm的作用 python的集成开发环境&#xff0c;功能如下&#xff1a; Project管理 智能提示 语法高亮 代码跳转 调试代码 解释代码(解释器) 框架和库 2&#xff09;下载与安装 下载地址&#xff1a;http://www.jetbrains.com/pycharm/download/#sectionwind…

进阶指针(一)

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 进阶指针&#xff08;一&#xff09; 0.回顾初阶指针1.字符指针1.1 相关面试题 2.数组指针3.指针数组3.1 数组指针的定义3.2 &数组名VS数组名3.3 数组指针的使用 4.数组传参和指针传参4.…

Linux中配置sudo用户访问权限

一、如何在 Linux 中配置 sudo 的访问权限 1.1、添加一个Linux普通用户有 sudo 权限 [root@localhost ~]# useradd test // 创建一个普通用户为:test [root@localhost ~]# [root@localhost ~]# passwd test // 设置用户test密码为:test Changing password for user te…