unity对象池系统

news2024/12/25 23:50:51

当游戏场景中出现大量的可重复利用的物体时,通过Destory来销毁再创建会触发不必要的GC回收机制,浪费性能,我们可以利用unity自带的对象池系统,从而节约性能来得到同样的效果。

为了使用这个对象池系统,我写了一个瞬间产生多枚子弹的测试脚本如下:

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

public class UnlimitedSwordSystem : MonoBehaviour
{
     public GameObject projiectilePrefab;

     public Rigidbody2D rigidbody2d;

     private int projectileNum=20;

     private Vector2 CreatPosition;

     GameObject projectile;
   
    private Coroutine launch3times;

    
    public void CreatProjectiles()
    {
        if(transform.GetComponent<SkillTrigger>().available==false)return;
        if(launch3times!=null)
        {
            StopCoroutine(launch3times);
        }
        launch3times=StartCoroutine("CreatProjectile");   
    }

    private IEnumerator CreatProjectile()
    {
        int k=2;
        while(k>=0)
        {
            k--;
            for(int i=0;i<projectileNum;i++)
        {
            CreatPosition=Random.insideUnitCircle*1.5f;

            projectile = Instantiate(projiectilePrefab, 
            CreatPosition+rigidbody2d.position,
            Quaternion.identity);
        
            launch(CreatPosition);
        }     
            yield return new WaitForSeconds(0.3f);
        }
    }

    
    void launch(Vector2 p)
    {
        projectile.GetComponent<Projectile>().Launch(p.normalized,500);
    }
}

这个脚本可以在瞬间分三次产生共60枚子弹,运行游戏,打开Profiler,可以看到GC Allocated In Frame有明显波动

 接下来使用对象池来优化

创建一个脚本pool,使用unity的对象池需引入UnityEngine.Pool;

从对象池中取出和放入对应着Get和Release这两个函数:

 

为了实现对象池,必须修改一下子弹的脚本,让子弹停留2秒后回收入对象池而非摧毁

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

public class Projectile : MonoBehaviour
{
    System.Action<Projectile>dea;
    public void SetDea(System.Action<Projectile> dea)
    {
        this.dea=dea;
    }
    private Rigidbody2D rigidbody2d;
    public int DamageValue=1;

    void Awake()    //在Start之前调用
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
    }

    public void Launch(Vector2 direction,float force)
    {
        rigidbody2d.AddForce(direction*force);
    }


    float lifeTime=2;
    bool IsActive=true;
    private void Update()
    {
        // if (transform.position.magnitude > 250f)
        // {
        //     Destroy(gameObject);
        // }
        if(!IsActive)return;
        
        lifeTime-=Time.deltaTime;
        if(lifeTime<=0)
        {
            lifeTime=2;
            dea.Invoke(this);

        }
    }

创建对象池所需的参数:

 createFunc:

创建一个对象,值得注意的是当Get不能得到一个对像时,会调用这个方法创建对象。

actionOnGet:

调出对象池对象时要执行的功能

actionOnRelease:

回收对象到对象池时要执行的功能

actionOnDestroy:

摧毁对象池中对象要执行的操作

collectionCheck:

是否开启回收检测功能

defaultCapacity:

对象池的默认容量,和链表或队列类似,当容量不足时会自动扩容。

maxSize:

限制对象池的最大容量,防止对象池的无限扩张,如果maxSize已满,当调用Release函数时,这个Release函数将会忽略。

对象池:

public class Pool : MonoBehaviour
{
    [SerializeField] Projectile prefab;
    [SerializeField] int defaultSize=100;
    [SerializeField] int maxSize=500;
    ObjectPool<Projectile>pool;

    [SerializeField] Rigidbody2D rigidbody2d;
    private void Awake() {
        pool=new ObjectPool<Projectile>(OnCreatPoolItem,OnGetPoolItem,OnReleasePoolItem,
        OnDestoryPoolItem,true,defaultSize,maxSize);
    }

    private void Update() {
        var p=pool.Get();
        p.transform.position=rigidbody2d.position+ Random.insideUnitCircle*2.5f;
    }

    private void OnDestoryPoolItem(Projectile projectile)
    {
        Destroy(projectile.gameObject);
    }

    private void OnReleasePoolItem(Projectile projectile)
    {
        projectile.gameObject.SetActive(false);
    }

    private void OnGetPoolItem(Projectile projectile)
    {
        projectile.gameObject.SetActive(true);
    }

    private Projectile OnCreatPoolItem()
    {
        var projectile=Instantiate(prefab,transform);
        projectile.SetDea(delegate{pool.Release(projectile);});

        return projectile;
    }
}

运行游戏可以看到,GC Allocated In Frame在对象池稳定运行后为0

 

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

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

相关文章

element-plus 报错 ResizeObserver loop limit exceeded 解决

使用Element-plus&#xff0c;页面重置大小时&#xff0c;出现如下报错&#xff1a; Uncaught runtime errors: ERROR ResizeObserver loop limit exceeded at handleError (webpack-internal:///./node_modules/webpack-dev-server/client/overlay.js:252:58) at ev…

DETR3D: 3D Object Detection from Multi-view Images via 3D-to-2D Queries

DETR3D: 3D Object Detection from Multi-view Images via 3D-to-2D Queries 目的 本文提出了一个 仅使用 2D 信息的&#xff0c;3D 目标检测网络&#xff0c;并且比依赖与 密集的深度预测 或者 3D 重建的过程。该网络使用了 和 DETR 相似的 trasformer decoder &#xff0c;…

SpringBoot中集成jasypt-spring-boot实现配置文件数据加密脱敏

场景 经常会遇到这样一种情况&#xff1a;项目的配置文件中总有一些敏感信息&#xff0c;比如数据源的url、用户名、 密码....这些信息一旦被暴露那么整个数据库都将会被泄漏&#xff0c;那么如何将这些配置隐藏呢。 除了使用手动将加密之后的配置写入到配置文件中&#xff…

Win把老外惹恼了!

随着Windows 10创意者更新&#xff08;民间称Win10.3&#xff09;推送规模的加大&#xff0c;其暴露出来的槽点越来越多。 此前&#xff0c;我们已经报道过新版的Defender升级为安全助手&#xff0c;类似于国内有名的xx管家和数字卫士&#xff0c;全面接管PC健康事务。 然而&a…

【css】用css样式快速写右上角badge徽标,颜色设置为渐变色

先看效果展示&#xff0c;已公开显示在图片卡片的右上角。 首先是dom代码&#xff1a;需要两个view或者div&#xff0c;public-badge是“已公开”那个矩形&#xff0c;show-signal是右边那个下三角&#xff0c;也就是阴影部分&#xff0c;这样看起来比较有立体感。 <view…

Linux驱动进阶(四)——内外存访问

文章目录 前言内存分配kmalloc函数vmalloc()函数后备高速缓存 页面分配内存分配物理地址和虚拟地址之间的转换 设备I/O端口的访问Linux I/O端口读写函数I/O内存读写使用I/O端口 小结 前言 驱动程序加载成功的一个关键因素&#xff0c;就是内核能够为驱动程序分配足够的内存空间…

论文解读:Inpaint Anything: Segment Anything Meets Image Inpainting

论文&#xff1a;https://arxiv.org/pdf/2304.06790.pdf 代码&#xff1a;https://github.com/geekyutao/Inpaint-Anything 图1&#xff1a;Inpaint Anything示意图。用户可以通过点击图像中的任何对象来选择它。借助强大的视觉模型&#xff0c;例如SAM[7]、LaMa [13]和稳定扩散…

我叫李明,我是一名开发人员

目录 一、这是一个故事 二、不屈不挠的李明 三、化解于无形 四、总结 一、这是一个故事 这个故事的主人公是一个年轻的程序员&#xff0c;他叫做李明。李明是一名技术过硬、工作认真负责的程序员&#xff0c;他的工作是开发一款新的软件产品。这款软件是一款在线购物平…

【Java基础】第四章 Object 类应用

系列文章目录 [Java基础] 第一章 String类应用及分析 [Java基础] 第二章 数组应用及源码分析 [Java基础] 第三章 StringBuffer 和 StringBuilder 类应用及源码分析 [Java基础] 第四章 Object 类应用 文章目录 系列文章目录前言一、如何使用Object&#xff1f;1.1、显式继承1.2…

c++内存映射文件

概念 将一个文件直接映射到进程的进程空间中&#xff08;“映射”就是建立一种对应关系,这里指硬盘上文件的位置与进程逻辑地址空间中一块相同区域之间一 一对应,这种关系纯属是逻辑上的概念&#xff0c;物理上是不存在的&#xff09;&#xff0c;这样可以通过内存指针用读写内…

Web-登录功能实现(含JWT令牌)

登录功能 这个登陆功能先不返回JWT令牌 登陆会返回JWT令牌 一会在登陆验证时讲解JWT令牌&#xff08;返回的data就是它&#xff09; 登录校验 概述 就是你比如复制一个url 用一个未曾登陆对应url系统的浏览器访问 他会先进入登陆页面 登陆校验就是实现这个功能 简而言之…

基于EasyExcel的单元格合并自定义算法处理

基于EasyExcel导出Excel后&#xff0c;通过对合并单元格的简单规则配置&#xff0c;实现如下图所示的单元格合并效果&#xff1a; 效果截图 原表格数据如下&#xff1a; 通过配置单元格合并规则后&#xff0c;生成的合并后的表格如下&#xff1a; 注&#xff1a;其中第三列&a…

Android Studio连接安卓手机

1. 创建项目 2. 下载Google USB Driver 点击右上角红框的【SDK Manager】->【SDK Tools】。 也可以在 【tools】->【SDK Manager】->【SDK Tools】下进入。 点击Google USB Driver&#xff0c;下载后点ok。 3. 环境变量 右键【我的电脑】->【高级系统设置】-&g…

基于微信小程序的高校新生自助报道系统设计与实现(Java+spring boot+MySQL+小程序)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于微信小程序的高校新生自助报道系统设计与实现&#xff08;Javaspring bootMySQL微信小程序&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1…

123、仿真-基于51单片机的电流控制仿真系统设计(Proteus仿真+程序+原理图+参考论文+配套资料等)

方案选择 单片机的选择 方案一&#xff1a;STM32系列单片机控制&#xff0c;该型号单片机为LQFP44封装&#xff0c;内部资源足够用于本次设计。STM32F103系列芯片最高工作频率可达72MHZ&#xff0c;在存储器的01等等待周期仿真时可达到1.25Mip/MHZ(Dhrystone2.1)。内部128k字节…

java报错- 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中。

SpringBoot使用了3.0或者3.0以上&#xff0c;因为Spring官方发布从Spring6以及SprinBoot3.0开始最低支持JDK17&#xff0c;所以仅需将SpringBoot版本降低为3.0以下即可。

ES6类-继承-Symbol-模版字符串

目录 类 继承 ES5 如何继承 ES6继承 Symbol 用途 可以产生唯一的值&#xff0c;独一无二的值 解决命名冲突 getOwnPropertySymbols() 作为全局注册表 缓存 Symbol.for() 消除魔术字符串 模版字符串 类 在javascript语言中&#xff0c;生成实例对象使用构造函数&#xf…

数据库基本操作-----数据库用户管理和授权

目录 一、数据库用户管理 1&#xff0e;新建用户 2&#xff0e;查看用户信息 3&#xff0e;重命名用户 4&#xff0e;删除用户 ​编辑5&#xff0e;修改当前登录用户密码 6&#xff0e;修改其他用户密码 7&#xff0e;忘记 root 密码的解决办法 &#xff08;1&#xff09;修…

Redis数据类型 — List

List 列表是简单的字符串列表&#xff0c;按照插入顺序排序&#xff0c;可以从头部或尾部向 List 列表添加元素。 List内部实现 List 类型的底层数据结构是由双向链表或压缩列表实现的&#xff1a; 如果列表的元素个数小于 512 个&#xff08;默认值&#xff0c;可由 list-m…

详解Single-Shot Alignment Network (S2A-Net) 基于遥感图像的特征对齐旋转目标检测

引言 目标检测&#xff1a;把图像中的物体使用方框标记起来&#xff0c;不同类别物体应使用不同颜色 目标检测其实是寻找物体边界框(bounding box)回归问题(regression)和对物体分类问题(classification)的统一 遥感目标检测&#xff1a;普通的目标检测是日常生活中的横向的图…