Unity——对象池

news2024/11/20 23:30:09

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


一、为什么要使用对象池

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

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

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

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

二、简易对象池实例 

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

对象池中的大量物体,如果用一个容器管理,则用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为1
        Debug.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.coloradmin.cn/o/1031646.html

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

相关文章

java用easyexcel按模版导出

首先在项目的resources下面建一个template包&#xff0c;之后在下面创建一个模版&#xff0c;模版格式如下&#xff1a; 名称为 financeReportBillStandardTemplateExcel.xlsx&#xff1a; {.fee}类型的属性值&#xff0c;是下面实体类的属性&#xff0c;要注意这里面的格式&a…

iPhone15拉胯,国产手机用折叠屏大反攻!

文 | 智能相对论 作者 | K星 iPhone偷懒式的15代机型发布&#xff0c;让市场大跌眼镜&#xff0c;虽然在莫名的宗教虔诚下依旧卖得很好&#xff0c;但苹果走下神坛之巅已经板上钉钉。 但是&#xff0c;苹果从最高处摔落&#xff0c;却依旧在神坛之上&#xff0c;iPhone15拉胯…

【STM32笔记】HAL库定时器捕获配置、操作及通用函数定义

【STM32笔记】HAL库定时器捕获配置、操作及通用函数定义 文章目录 定时器捕获设置输入捕获滤波器设置输入捕获极性设置输入捕获映射关系设置输入捕获分频器 定时器配置定时器捕获函数全局变量定时器回调和定时器捕获回调频率计算 附录&#xff1a;Cortex-M架构的SysTick系统定…

css自学框架之二级下拉菜单

下拉菜单是我们开发中最常见&#xff0c;最常用的&#xff0c;今天我们就自学二级下来菜单。首先看一下最终效果&#xff1a; 一、css代码 .arrow-down::before {content: ""; width: 10px;height: 10px;border: solid ;border-width: 2px 2px 0 0;border-color: …

BIGEMAP在土地规划中的应用

工具 Bigemap gis office地图软件 BIGEMAP GIS Office-全能版 Bigemap APP_卫星地图APP_高清卫星地图APP 1.使用软件一般都用于套坐标&#xff0c;比如我们常见的&#xff08;kml shp CAD等土建规划图纸&#xff09;以及一些项目厂区红线&#xff0c;方便于项目选址和居民建…

软考复习 -- 计算机网络

1 网络互连设备 物理层&#xff1a;中继器和集线器&#xff08;多路中继器&#xff09;数据链路层&#xff1a;网桥和交换机&#xff08;多端口网桥&#xff09;网络层&#xff1a;路由器应用层&#xff1a;网关 2 广播域和冲突域 3 协议簇 4 网际层协议 4 TCP和UDP 4.1 TC…

零基础学前端(五)HTML+CSS实战:模仿百度网站首页

1. 该篇适用于从零基础学习前端的小白 2. 初学者不懂代码得含义也要坚持模仿逐行敲代码&#xff0c;以身体感悟带动头脑去理解新知识 一、实战&#xff1a;将百度网站首页补全 上一篇零基础学前端&#xff08;三&#xff09;重点讲解 HTML-CSDN博客我们已经将顶部两侧内容已经…

人机交互——对话管理

​人机交互中的对话管理主要是指在人机交互过程中&#xff0c;对交互的对话内容和流程进行管理&#xff0c;以实现自然、流畅、高效的交互效果。对话管理包括对话状态追踪、对话策略优化等多个方面。 对话状态追踪是指对当前对话的状态进行跟踪&#xff0c;例如对用户输入的语…

Observability:检测 OpenTelemetry 的推荐指南

作者&#xff1a;Bahubali Shetti OpenTelemetry (OTel) 正在稳步获得广泛的行业采用。 作为主要的云原生计算基金会 (CNCF) 项目之一&#xff0c;其提交数量与 Kubernetes 一样多&#xff0c;它正在获得主要 ISV 和云提供商的支持&#xff0c;为该框架提供支持。 许多来自金融…

ChatGLM GPT原理介绍

图解GPT 除了BERT以外,另一个预训练模型GPT也给NLP领域带来了不少轰动,本节也对GPT做一个详细的讲解。 OpenAI提出的GPT-2模型(https://openai.com/blog/better-language-models/) 能够写出连贯并且高质量的文章,比之前语言模型效果好很多。GPT-2是基于Transformer搭建的,相…

【校招VIP】前端JS之深拷贝和浅拷贝

考点介绍 js中的浅拷贝和深拷贝&#xff0c;只是针对复杂数据类型(Objcet&#xff0c;Array)的复制问题。简单来讲浅拷贝和深拷贝都可以实现在原有对象的基础上再生成一份的作用。但是根据新生成的对象能否影响到原对象可以分为浅拷贝和深拷贝。 前端JS之深拷贝和浅拷贝-相关题…

ArcGIS 10.3软件安装包下载及安装教程!

【软件名称】&#xff1a;ArcGIS 10.3 【安装环境】&#xff1a;Windows 【下载链接 】&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1K5ab7IHMYa23HpmuPkFa1A 提取码&#xff1a;oxbb 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 软件解压码点击原文…

Flink--4、DateStream API(执行环境、源算子、基本转换算子)

星光下的赶路人star的个人主页 注意力的集中&#xff0c;意象的孤立绝缘&#xff0c;便是美感的态度的最大特点 文章目录 1、DataStream API1.1 执行环境&#xff08;Execution Environment&#xff09;1.1.1 创建执行环境 1.2 执行模式&#xff08;Execution Mode&#xff09;…

安装gpu版本的paddle

安装gpu版本的paddle python -m pip install paddlepaddle-gpu2.3.2.post111 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html以上支持cuda11.1版本 其他需求可查阅文档在这里

redis如何清空当前缓存和所有缓存

Windows环境下使用命令行进行redis缓存清理 redis安装目录下输入cmdredis-cli -p 端口号flushdb 清除当前数据库缓存flushall 清除整个redis所有缓存keys * 查看所有key值del key 删除指定索引的值 注意&#xff1a; 我们清空缓存的时候&#xff0c;需要确保redis-…

【ONE·Linux || 进程间通信】

总言 进程间通信&#xff1a;简述进程间通信&#xff0c;介绍一些通信方式&#xff0c;管道通信&#xff08;匿名、名命&#xff09;、共享内存等。 文章目录 总言1、进程间通信简述2、管道2.1、简介2.2、匿名管道2.2.1、匿名管道的原理2.2.2、编码理解&#xff1a;用fork来共…

GIT提示Another git process seems to be running in this repository

解决方法 1、进入项目里面的.git文件里面找到index.lock删除即可。

【漏洞复现】易思智能物流无人值守系统文件上传

本文由掌控安全学院 - 江月 投稿 【产品介绍】 易思无人值守智能物流系统是一款集成了人工智能、机器人技术和物联网技术的创新产品。它能够自主完成货物存储、检索、分拣、装载以及配送等物流作业&#xff0c;帮助企业实现无人值守的智能物流运营&#xff0c;提高效率、降低…

基于SpringBoot的高校心理教育辅导系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 学生功能模块的实现 管理员功能模块的实现 教师功能模块的实现 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着Internet技术的发展&#xff0c;心理教育辅导系统应运而生&#xff0c;心理教育辅导系统为用户…

外汇天眼:意大利CONSOB下令封锁五个非法投资网站!

意大利的公司和交易委员会&#xff08;CONSOB&#xff09;已下令封锁五个非法投资网站的访问权限。最新命令针对的网站包括&#xff1a; 1.Ether Arena Ltd 2.ImpresaMarkets 3.Fx-vita 4.Keysreim 5.Bitbinx.ltd CONSOB发布这些命令时&#xff0c;利用了源自“Decreto c…