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

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

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

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

相关推荐
avi91117 小时前
[AI相关]Unity的C#代码如何简写
unity·c#·语法糖
虾球xz13 小时前
游戏引擎学习第114天
学习·游戏引擎
虾球xz14 小时前
游戏引擎学习第109天
学习·游戏引擎
心疼你的一切15 小时前
C# 中关于补位的写法 PadLeft,PadRight 函数
开发语言·unity·c#·游戏引擎·csdn·心疼你的一切
沐沐森的故事18 小时前
Unity for Python —— 强大的 Python 脚本支持提升 Unity 编辑器效率
python·unity·编辑器·pythonrunner·pythonengine
xklcy20 小时前
Unity通过Vosk实现离线语音识别方法
unity·语音识别
虾球xz1 天前
游戏引擎学习第113天
学习·游戏引擎
老朱佩琪!2 天前
在Unity中用简单工厂模式模拟原神中的元素反应
unity·简单工厂模式
虾球xz2 天前
游戏引擎学习第111天
学习·游戏引擎
程序猿多布2 天前
预定义委托(C# and Unity)
unity·c#