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

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

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

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

相关推荐
C MIKE1 小时前
unity免费资源2025-1-10
unity·游戏引擎
恬静的小魔龙2 小时前
【Unity3D日常开发】Unity3D中打开Window文件对话框打开文件(PC版)
3d·unity·编辑器·游戏引擎·音视频
90后小陈老师2 小时前
Unity搭配VS Code使用
unity·游戏引擎
FatherOfCodingMan2 小时前
unity PrefabUtility 接口使用记录
unity·游戏引擎
林枫依依2 小时前
Unity 视频导入unity后,播放时颜色变得很暗很深,是什么原因导致?
unity·游戏引擎
め.2 小时前
Unity的Transform类
unity·游戏引擎
人生不过一瞬间2 小时前
Unity 自定义批量打包工具
windows·unity·游戏引擎
Thomas_YXQ8 小时前
Unity3D中的Lua、ILRuntime与HybridCLR/huatuo热更对比分析详解
开发语言·junit·性能优化·c#·游戏引擎·lua·unity3d
598866753@qq.com8 小时前
Unity Protobuf实践
unity·游戏引擎
TYayyyyy21 小时前
unity下载newtonsoft-json
unity·json