Unity对象池的简单理解

这篇具有很好参考价值的文章主要介绍了Unity对象池的简单理解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是对象池?

  通常我们需要用到某个游戏对象时,我们会在内存中分配一部分空间new一个对象出来,之后在该对象完成任务之后,再将其摧毁,释放掉内存。在Unity中就是我们在需要的时候调用Instantiate()函数来生成一个游戏对象。

	GameObject gameObject = GameObject.Instantiate(prefab);

  在用完该对象之后,调用Destory()函数将其摧毁。

	Destoty(gameobject);

  Unity引擎的自动内存管理系统会帮我们完成垃圾回收(GC)的工作,但垃圾回收本身也是要消耗性能的,如果对象过多就会十分消耗性能,如果我们要频繁地生成与摧毁对象,GC就会非常忙,导致游戏卡顿甚至崩溃,因此我们应该尽可能少的触发垃圾回收机制,这就要用到对象池了。

对象池的原理:

  在游戏初始化的阶段,先取出一块完整的内存空间,用来生成运行过程中需要用到的对象,让它们预备好随时被启用。在我们需要用到某个对象的时候,我们不再new新的对象,而是从预备好的这块内存空间中,即对象池中取出来该对象使用,用完之后再将该对象放回对象池,随取随用。
unity 对象池,Unity,unity,游戏引擎

使用对象池与不使用对象池对比:

unity 对象池,Unity,unity,游戏引擎
  很明显,使用对象池相比于不使用对象池会给游戏带来显著的性能提升,尤其是对于像是射击类游戏这种需要创建大量的子弹对象的游戏,使用对象池是必不可少的,同时使用对象池还能够减少目标游戏平台的性能消耗,增加游戏运行流畅度。

创建对象池:

  这里我们用队列(Queue)的数据结构来存储我们要实例化的游戏对象,即我们做好的预制体(Prefabs)。

	Queue<GameObject> queue;
创建对象池的步骤:

unity 对象池,Unity,unity,游戏引擎
  (1)生成备用对象,禁用它们,准备随时被启用,将它们挂载到同一个父对象上,将对象初始化。

	//复制预制体对象 加入对象池
	GameObject Copy()
    {
        var copy = GameObject.Instantiate(prefab, parent);
        copy.SetActive(false);
        return copy;
    }
    //初始化对象池 将所有对象入队
    public void Init(Transform parent)
    {
        queue = new Queue<GameObject>();
        this.parent = parent;
        
        for (int i = 0; i < size; i++)
        {
            queue.Enqueue(Copy());
        }
    }

  (2)从池中取出可用对象,将其出队,若池中没有可用对象,则调用生成备用对象函数。

    //从池中取出可用的对象
    GameObject AvailableObject()
    {
        GameObject avaliableObject = null;
        if (queue.Count > 0) //&& !queue.Peek().activeSelf
        {
            avaliableObject = queue.Dequeue();
        }
        else
        {
            avaliableObject = Copy();
        }

        //queue.Enqueue(avaliableObject);
        return avaliableObject;
    }

  (3)启用可用对象,可以根据自己的实际要求写几个重载,让启用对象做出某些选择。

	//启用可用的对象
    public GameObject PreparedObject()
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);

        return proparedObject;
    }

    //启用可用的对象 并让其出现在场景中的某个位置
    public GameObject PreparedObject(Vector3 position)
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);
        proparedObject.transform.position = position;

        return proparedObject;
    }

    //启用可用的对象 并让其出现在场景中的某个位置 并使其旋转某个角度
    public GameObject PreparedObject(Vector3 position, Quaternion rotation)
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);
        proparedObject.transform.position = position;
        proparedObject.transform.rotation = rotation;

        return proparedObject;
    }

    //启用可用的对象 并让其出现在场景中的某个位置 并使其旋转某个角度 并缩放其大小
    public GameObject PreparedObject(Vector3 position, Quaternion rotation, Vector3 localScale)
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);
        proparedObject.transform.position = position;
        proparedObject.transform.rotation = rotation;
        proparedObject.transform.position = localScale;

        return proparedObject;
    }

  (4)让完成任务的对象返回对象池。

	//让已用过的对象返回对象池(可与启用写在同一函数中)
    public void Return(GameObject gameObject)
    {
        queue.Enqueue(gameObject);
    }

简单对象池完整代码:

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

[System.Serializable]
public class Pool
{
    public GameObject Prefab => prefab; 

    [SerializeField] GameObject prefab;
    //存储所有复制体的数量
    [SerializeField] int size = 1;

    //池的父对象
    Transform parent;

    Queue<GameObject> queue;

    //初始化对象池 将所有对象入队
    public void Init(Transform parent)
    {
        queue = new Queue<GameObject>();
        this.parent = parent;
        
        for (int i = 0; i < size; i++)
        {
            queue.Enqueue(Copy());
        }
    }

    //复制预制体对象 加入对象池
    GameObject Copy()
    {
        var copy = GameObject.Instantiate(prefab, parent);
        copy.SetActive(false);
        return copy;
    }

    //从池中取出可用的对象
    GameObject AvailableObject()
    {
        GameObject avaliableObject = null;
        if (queue.Count > 0) //&& !queue.Peek().activeSelf
        {
            avaliableObject = queue.Dequeue();
        }
        else
        {
            avaliableObject = Copy();
        }

        //queue.Enqueue(avaliableObject);
        return avaliableObject;
    }

    //启用可用的对象
    public GameObject PreparedObject()
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);

        return proparedObject;
    }

    //启用可用的对象 并让其出现在场景中的某个位置
    public GameObject PreparedObject(Vector3 position)
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);
        proparedObject.transform.position = position;

        return proparedObject;
    }

    //启用可用的对象 并让其出现在场景中的某个位置 并使其旋转某个角度
    public GameObject PreparedObject(Vector3 position, Quaternion rotation)
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);
        proparedObject.transform.position = position;
        proparedObject.transform.rotation = rotation;

        return proparedObject;
    }

    //启用可用的对象 并让其出现在场景中的某个位置 并使其旋转某个角度 并缩放其大小
    public GameObject PreparedObject(Vector3 position, Quaternion rotation, Vector3 localScale)
    {
        GameObject proparedObject = AvailableObject();

        proparedObject.SetActive(true);
        proparedObject.transform.position = position;
        proparedObject.transform.rotation = rotation;
        proparedObject.transform.position = localScale;

        return proparedObject;
    }

    //让已用过的对象返回对象池(可与启用写在同一函数中)
    public void Return(GameObject gameObject)
    {
        queue.Enqueue(gameObject);
    }
}

  以上是我对实现对象池的理解,写为博客,作为自己的学习记录与参考,欢迎指正。文章来源地址https://www.toymoban.com/news/detail-810483.html

到了这里,关于Unity对象池的简单理解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity--随机生成游戏对象

    在脚本中声明数组 RandomObjects 用于保存生成对象的类型,在project文件中拖入对象。 先将脚本拖到一个对象上,然后点击检查器-覆盖-应用到全部,这样将使所有预制件都拥有该属性。

    2024年02月15日
    浏览(40)
  • Unity vs Godot :哪个游戏引擎更适合你?

    游戏引擎的选择对开发过程和最终产品质量有着重大影响。近年来,Godot和Unity这两款引擎受到广泛关注。本文将从多个维度对两者进行比较,以期为开发者提供正确的选择建议。 Godot和Unity都有各自的优势,没有绝对的好坏之分。Godot开源免费,上手简单,更适合2D和小型游戏

    2024年01月23日
    浏览(94)
  • 30分钟了解所有引擎组件,132个Unity 游戏引擎组件速通!【收藏 == 学会】

    🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN 🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 🌲Unity实战100例专栏推荐:Unity 实战100例 教程 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📆 未来很长

    2024年02月11日
    浏览(71)
  • Unity Physics2D 2d物理引擎游戏 笔记

    2d 材质 里面可以设置 摩擦力 和 弹力 Simulated:是否在当前的物理环境中模拟,取消勾选该框类似于Disable Rigidbody,但使用这个参数更加高效,因为Disable会销毁内部产生的GameObject,而取消勾选Simulated只是禁用。 Kinematic 动力学刚体 动力学刚体不受重力和力的影响,而受用户的

    2023年04月24日
    浏览(121)
  • Unity基础课程之物理引擎6-关于物理材质的使用和理解

     每个物体都有着不同的摩擦力。光滑的冰面摩擦力很小,而地毯表面的摩擦力则很大。另外每种材料也有着不同的弹性,橡皮表面的弹性大,硬质地面的弹性小。在Unity中这些现象都符合日常的理念。虽然从原理上讲,物体的摩擦力和弹性有着更复杂的内涵,例如普通的钢板

    2024年02月07日
    浏览(47)
  • Unity 3D:获取未激活游戏对象的方法

    一、获取已激活游戏对象 Gameobject.Find(\\\"游戏对象名\\\") //根据对象名直接获取游戏对象 这个方法可以找到指定的对象,但是一些缺陷。 1、如果场景中有重名,此方法找到的是Hierarchy从上至下第一次出现此对象名的对象。 2、如果对象的activeSelf为false,那么这个方法永远无法找到

    2023年04月08日
    浏览(44)
  • Unity和UE4两大游戏引擎,你该如何选择?

    目录 游戏引擎 2 —— 难易区别 编程语言 3 —— 游戏产品 UE4制作的游戏产品  Unity制作的游戏产品  产品类型 5 —— 资源商店 6 —— 人才需求 平均薪资 总结      Unity和UE4都是游戏引擎,所谓游戏引擎就是集成了复杂功能的游戏开发软件,他们帮我们实现了复杂的底层逻

    2023年04月08日
    浏览(69)
  • GODOT游戏引擎简介,包含与unity性能对比测试,以及选型建议

    GODOT,是一个免费开源的3D引擎。本文以unity作对比,简述两者区别和选型建议。由于是很久以前写的ppt,技术原因视频和部分章节丢失了。建议当做业务参考。 GODOT目前为止遇到3个比较重大的机遇,第一个是oprea的合作奖,第二个是用支持c#换来的微软的投资,第三个是虚幻

    2024年02月14日
    浏览(83)
  • Unity中获取游戏对象的几种方式

    在学习如何获取物体和组件时先明白说明什么是物体,组件和对象。 物体:unity中在层级显示的东西都可以叫做物体 组件:unity中提供了大量已经写好的组件,比如刚体,碰撞体等,自己 编写的脚本也是一种组件类 对象:挂载到物体上的脚本是一个实例化的组件,也就是一

    2024年01月17日
    浏览(37)
  • unity 之 GetComponent 获取游戏对象上组件实例方法

    GetComponent 是Unity引擎中用于获取游戏对象上组件实例的方法。它允许您从游戏对象中获取特定类型的组件,以便在脚本中进行操作和交互。 GetComponent ComponentType (): 这是一个泛型方法,用于从当前游戏对象上获取指定类型的组件。在 ComponentType 部分,您应该提供您想要获取的

    2024年02月02日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包