unity中的万能对象池

yizhihongxing

Unity中的万能对象池

在Unity开发中,对象池是一个非常常用的技术,在需要频繁创建和销毁游戏对象的场景下,使用对象池能够提高游戏运行的效率和性能。

不过,与常规的对象池不同的是,本文介绍的是一种使用泛型和接口实现的万能对象池,不仅可以复用GameObject对象,同时也能够重复使用所有继承自MonoBehaviour的组件。

实现方式

首先,定义一个接口IPoolable,它包含了两个方法,OnSpawnOnDespawn,分别代表对象被获取和归还时的操作:

public interface IPoolable
{
    void OnSpawn();
    void OnDespawn();
}

接着,定义一个泛型类ObjectPool<T>,它继承自MonoBehaviour,因为我们需要使用协程来实现对象的自动归还。ObjectPool<T>有以下属性和方法:

public class ObjectPool<T> : MonoBehaviour where T : Component, IPoolable
{
    [SerializeField]
    private T prefab;

    private Queue<T> objectQueue = new Queue<T>();

    public T Get()
    {
        if (objectQueue.Count == 0)
        {
            return Instantiate(prefab);
        }
        else
        {
            T objectToGet = objectQueue.Dequeue();
            objectToGet.gameObject.SetActive(true);
            objectToGet.OnSpawn();
            return objectToGet;
        }
    }

    public void Return(T objectToReturn)
    {
        objectToReturn.OnDespawn();
        objectToReturn.gameObject.SetActive(false);
        objectQueue.Enqueue(objectToReturn);
    }
}

其中,prefab属性为对象池内保存的对象预制体。objectQueue是一个FIFO的队列,用来存储已经使用过的对象。Get()方法会从队列中获取一个对象,如果队列为空就新建一个对象。获取到的对象需要被激活,并调用它的OnSpawn()方法。Return(objectToReturn)方法则是将对象归还至队列,调用它的OnDespawn()方法,并设置它的游戏对象为不激活状态。

最后,我们让需要使用对象池的GameObject继承自IPoolable接口,并手动实现OnSpawnOnDespawn方法。这样,我们就可以把任意继承自MonoBehaviour的组件加入到我们的对象池中,用法非常灵活。

使用示例

假设我们想要使用这个万能对象池来实现子弹的复用,现在我们需要在场景中创建一个子弹预制体,预制体上需要挂载Bullet脚本:

public class Bullet : MonoBehaviour, IPoolable
{
    public float speed = 10.0f;
    public float lifetime = 5.0f;

    private Coroutine lifetimeCoroutine;

    public void OnSpawn()
    {
        lifetimeCoroutine = StartCoroutine(LifetimeTimer());
    }

    public void OnDespawn()
    {
        StopCoroutine(lifetimeCoroutine);
    }

    private IEnumerator LifetimeTimer()
    {
        yield return new WaitForSeconds(lifetime);
        ObjectPool<Bullet>.Instance.Return(this);
    }

    void Update()
    {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
}

Bullet脚本实现了IPoolable接口,并在OnSpawn方法中启动了一个携程,用来计算子弹的寿命。当寿命结束时,我们需要将子弹归还到对象池中。

在我们的游戏场景中创建一个空对象,将ObjectPool脚本挂载上去:

public class ObjectPool : MonoBehaviour
{
    public static ObjectPool Instance;

    void Awake()
    {
        Instance = this;
    } 
}

在需要使用子弹的脚本中,我们只需要调用ObjectPool<Bullet>.Instance.Get()方法获取一个子弹,而不是手动使用Instantiate来创建它:

ObjectPool<Bullet>.Instance.Get();

当需要归还对象时,调用Return()方法:

ObjectPool<Bullet>.Instance.Return(bullet);

总结

这篇文章介绍了一种使用泛型和接口实现的万能对象池,可以方便灵活地复用GameObject和所有继承自MonoBehaviour的组件。这种实现方式避免了重复编写对象池代码的麻烦,大大提高开发效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:unity中的万能对象池 - Python技术站

(0)
上一篇 2023年3月28日
下一篇 2023年3月28日

相关文章

  • Android SQLite数据库连接实现登录功能

    Android SQLite数据库连接实现登录功能攻略 1. 创建数据库和表格 首先,我们需要创建一个SQLite数据库和一个用于存储用户信息的表格。可以在SQLiteOpenHelper类中实现这一步骤。 public class DatabaseHelper extends SQLiteOpenHelper { private static final …

    other 2023年8月21日
    00
  • 无人深空分辨率低怎么办 游戏分辨率低机掉纹理解决方法

    针对“无人深空分辨率低怎么办,游戏分辨率低机掉纹理解决方法”这一问题,我来给出一个完整的攻略: 1. 解决无人深空分辨率低的问题 在游戏设置中将分辨率调整为更高的数值可以提升游戏画面的清晰度和细节。 另外,若电脑硬件足够强劲,可以尝试使用超采样(supersampling)技术,即在当前分辨率的基础上,提高内部渲染分辨率,再经过缩放输出到显示器上。 以下是超…

    other 2023年6月27日
    00
  • JVM学习笔记一:内存管理

    JVM学习笔记一:内存管理的完整攻略 Java虚拟机(JVM)是Java语言的核心,它负责将Java代码转换为可执行的机器码。在JVM中,内存管理是非常重要的一部分,它负责管理Java程序的内存分配和回收。本文将介绍JVM内存管理的基本原理和常用的内存管理技术。 JVM内存结构 JVM内存结构分为以下几个部分: 程序计数器(Program Counter R…

    other 2023年5月5日
    00
  • IntelliJ IDEA2020新增禅模式和LightEdit模式

    当用户使用 IntelliJ IDEA2020 进行代码编写时,可以通过新的禅模式和 LightEdit 模式来提升编程的效率和体验,下面我将为大家讲解详细的攻略。 禅模式 禅模式专为程序员提供一种精简的编码环境,旨在提供最大的注意力和舒适度。 如何开启禅模式? 打开 IntelliJ IDEA2020,进入编辑器界面。 在编辑器工具栏中找到 Zen Mod…

    other 2023年6月27日
    00
  • Vue折叠面板组件的封装

    Vue折叠面板组件的封装是在Vue框架下实现一种可折叠的面板组件,用于在界面中显示一些可收缩的内容,用户可通过点击操作来控制收缩和展开,下面将详细讲解如何实现其封装。 1. 创建Vue组件 首先,我们需要在Vue中创建一个折叠面板组件,具体实现如下: <template> <div class="collapse-panel&qu…

    other 2023年6月25日
    00
  • ORACLE workflow审批界面显示附件信息和附件的下载链接(转)

    ORACLE workflow审批界面显示附件信息和附件的下载链接(转) 在ORACLE workflow流程中,有时需要在审批的界面中显示附件信息,并可以提供附件的下载链接。这篇文章将介绍如何实现这个需求。 实现步骤 创建一个新的Item Type 在WorkFlow Builder中,使用管理员账号登录,并选择File > New > Ite…

    其他 2023年3月28日
    00
  • 教你如何通过Radmin拿服务器

    教你如何通过Radmin拿服务器其实就是指利用远程管理工具Radmin来获取目标服务器的控制权限。这里我将分几个步骤介绍一下整个攻略。 步骤一:获取目标服务器的IP地址 首先你需要获取目标服务器的IP地址,可以通过nmap、ping或其他工具来扫描得到。 步骤二:下载和安装Radmin Radmin是一款常用的远程管理工具,你只需要从官方网站下载并安装即可。…

    other 2023年6月27日
    00
  • 关于php:用括号括起来的逗号分隔字符串

    在MATLAB中,我们可以使用详尽而详尽的and和or条件if语句来实现多个条件的判断。本攻略将介绍如何在MATLAB中使用详尽而详尽的and和or条件if语句,并提供两个示例。 步骤一:使用详尽而详尽的and条件if语句 在MATLAB中,我们可以使用详尽而详尽的and条件if语句来实现多个条件的判断。以下是一个示例,展示了如何使用详尽而详尽的and条件i…

    other 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部