Unity中对象池的使用(用一个简单粗暴的例子)

问题描述:Unity在创建和销毁对象的时候是很消耗性能的,所以我们在销毁一个对象的时候,可以不用Destroy,而是将这个物体隐藏后放到回收池里面,当再次需要的时候如果回收池里面有之前回收的对象,就直接拿来用,这样就可以大量的创建和销毁物体。

首先创建一个子弹预制体,并添加刚体组件,然后创建一个Skill空对象和一个Skill脚本

cs 复制代码
using System.Collections;
using UnityEngine;

public class Skill : MonoBehaviour
{
    public int _SkillLv;//技能等级
    public GameObject bluut;//子弹预制体
    [Header("可调节参数")]
    //速度合成
    public float _Speedy;
    public float _Speedx;
    public float  _cd;
    void Start()
    {
        StartCoroutine(FireCoroutine());
    }
    //定义一个携程,用于在一定时间后发射子弹//间隔为_cd秒
    IEnumerator FireCoroutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(_cd);
            fashe(_SkillLv);
        }
    }
    //发射子弹的方法
    void fashe(int lv)
    {
        for (int i = 0; i < lv; i++)
        {
            GameObject bullet = Instantiate(bluut, transform.position, Quaternion.identity);
            int randomY = Random.Range(200, (int)_Speedy);
            int randomX = Random.Range(-(int)_Speedx, (int)_Speedx);
            bullet.GetComponent<Rigidbody2D>().AddForce(new Vector2(randomX, randomY));
            Destroy(bullet, 5f);
        }
    }
}

将Skill脚本加到Skill空对象上然后将子弹预制体拖入,然后运行游戏。

调整参数并观察游戏的帧率(可以看到在等级为10,cd为1的时候帧率还是挺高的)

上上强度(当等级为500,cd为1的时候可以看到此时的帧率下降明显)

现在看看加入对象池的效果

首先创建一个BulletPoolManager空对象和对应的脚本,并将脚本拖到空对象上

cs 复制代码
using System.Collections.Generic;
using UnityEngine;

public class BulletPoolManager : MonoBehaviour
{
    // 子弹的预制体
    public GameObject bulletPrefab;
    //初始化对象池
    private Queue<GameObject> pool = new Queue<GameObject>();
    //单例模式
    public static BulletPoolManager Instance;
    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
    //创建子弹的方法
    public GameObject GetBullet()
    {
        if (pool.Count > 0)
        {
            GameObject obj = pool.Dequeue();
            obj.SetActive(true);
            return obj;
        }
        else
        {
            // 如果对象池里面没有可用的子弹,则实例化一个新的子弹对象
            //注意这里是为了演示所有子弹是直接从预制体中实例化的,实际使用时,需要动态创建子弹对象
            GameObject newbullet = Instantiate(bulletPrefab);  
            return newbullet;
        }
    }

    // 回收子弹的方法
    public void ReturnBullet(GameObject bullet)
    {
        bullet.SetActive(false);
        bullet.transform.SetParent(transform);
        pool.Enqueue(bullet);
    }
}

将子弹的预制体拖到回收池对应位置(这里为了方便直接用拖的,实际使用的时候根据需要修改这里)

修改技能代码

主要修改的地方

cs 复制代码
using System.Collections;
using UnityEngine;

public class Skill : MonoBehaviour
{
    public int _SkillLv;//技能等级
    public GameObject bluut;//子弹预制体
    [Header("可调节参数")]
    //速度合成
    public float _Speedy;
    public float _Speedx;
    public float  _cd;
    void Start()
    {
        StartCoroutine(FireCoroutine());
    }
    //定义一个携程,用于在一定时间后发射子弹//间隔为_cd秒
    IEnumerator FireCoroutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(_cd);
            fashe(_SkillLv);
        }
    }
    //发射子弹的方法
    void fashe(int lv)
    {
        for (int i = 0; i < lv; i++)
        {
            GameObject bullet = BulletPoolManager.Instance.GetBullet();
            bullet.transform.position = transform.position;
            bullet.transform.parent = gameObject.transform;

            int randomY = Random.Range(200, (int)_Speedy);
            int randomX = Random.Range(-(int)_Speedx, (int)_Speedx);
            bullet.GetComponent<Rigidbody2D>().AddForce(new Vector2(randomX, randomY));

            StartCoroutine(ReturnBullet(bullet));
        }
    }
    IEnumerator ReturnBullet(GameObject bullet)
    {
        yield return new WaitForSeconds( 5f);
        BulletPoolManager.Instance.ReturnBullet(bullet);
    }
}

运行游戏并修改参数我们会发现同样等级10,cd=1的时候的帧率要高于不用回收池的时候。

试试等级500,cd为1

可以看到使用对象池还是有一点提升的。

你可以在这里看到回收的对象

这是用的对象池是用队列来存储回收的对象的,在实际开发中并不一定要使用队列,只要能存储多个对象的数据结构不管是泛型还是数组都可以当做对象池。

相关推荐
魔士于安2 天前
unity 丑陋哥布林 哥布林有humannoid 动画没 带动画
unity·游戏引擎·材质·贴图·模型
小贺儿开发3 天前
Unity 家居视频遥控(细节优化)
科技·unity·程序员·udp·视频·工具·通信
淡海水3 天前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
小小数媒成员4 天前
UGUI 性能优化(详细,全,深入)
开发语言·unity·游戏引擎
林川~014 天前
Unity新输入系统使用笔记
unity·input system
小贺儿开发4 天前
Unity 结合百度AI开放平台 手写文字识别
人工智能·科技·学习·unity·云服务·文字识别·手写文字
goujunwe5 天前
GEO 评估方法:如何自测你的内容,会不会被 AI 引用
搜索引擎·网络安全·游戏引擎·全文检索·中文分词
林川~015 天前
Unity 万能物理检测工具:射线检测 / 范围检测 / 层级过滤 / 编辑器可视化(可直接拿去用)
游戏·unity·c#·射线检测·通用工具
yi碗汤园5 天前
MQTT消息队列遥测传输协议
网络·网络协议·unity
林川~015 天前
Unity 常用 API 与核心类全解:从生命周期到协程,附性能避坑清单(Unity 6 适配)
unity·游戏引擎·常用api