全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货

Unity对象池的学习

发布时间:2022-07-29 16:40:00
发布人:wjy

  对象池在Unity3D中是极为重要的技术,在遇到需要大量重复创建、销毁的对象时,对象池可以将其存放入池中,反复利用,从而尽可能的重复使用内存中驻留的资源。

千锋教育

  对象池的典型用法就是射击游戏中的子弹。在不使用对象池时,子弹的“一生”是这样的:创建→产生作用→销毁;而使用对象池后,子弹的“一生”是这样的:从对象池中取出使用→产生作用→存放进对象池→从对象池中取出使用···

  显而易见的,该方法能避免重复对象的创建、销毁过程,节省内存空间的使用。以下为一个子弹对象池的大致创建过程

  首先是对象池创建

    //prefabPool = new PrefabPool(Resources.Load<Transform>("xxx"));加载本地预制

    //prefabPool.cullDespawned = true;自动清理对象池

    public static BulletPool bullet;//该部分用于初始化此对象池的配置

    public GameObject bulletObj;

    public int pooledAmount = 5;//初始化对象池中对象数量

    public bool lockPoolSize = false;//取消锁定对象池大小

    private List<GameObject> pooledObjects;//创建对象池链表

    private int currentIndex = 0;

    void Awake()

    {

        bullet = this;//实例化对象池

    }

在start()中初始化对象池链表

void Start()

    {

        pooledObjects = new List<GameObject>();

        for (int i = 0; i < pooledAmount; ++i)

        {

            GameObject obj = Instantiate(bulletObj);//创建子弹对象

            obj.SetActive(false);//将子弹对象的激活状态Active设置为false

            pooledObjects.Add(obj);//将子弹存放入对象池中

        }

    }

调用该子弹对象池中的可用子弹

public GameObject GetPooledObject()

    {

        for (int i = 0; i < pooledObjects.Count; ++i)//遍历对象池以寻找可用子弹

        {

            //从上一次调用的子弹的下一个开始寻找

            //例如上一次发射的子弹是对象池中序号为2的子弹,则本次调用对象池中子弹时从3开始检查是否可用

            int temI = (currentIndex + i) % pooledObjects.Count;

            if (!pooledObjects[temI].activeInHierarchy)//检查该对象的Active状态

            {

                currentIndex = (temI + 1) % pooledObjects.Count;

                return pooledObjects[temI];//如果Active为false则返回调用该对象

            }

        }

        if(!lockPoolSize)//若没有false状态的子弹供我们使用,则生成新的对象并加入对象池

        {

            GameObject obj = Instantiate(bulletObj);

            pooledObjects.Add(obj);

            return obj;

        }

        return null;

    }

  在对象池中寻找可用对象时,最初只通过遍历进行地毯式搜索。在实际使用时,经过频繁的调用后,会产生略微影响体验的卡顿,一开始以为是对象过多,机器的机能限制,后来查看到了一篇文章,指明了这一问题产生的原因。

  在寻找可用对象时,如果每次遍历都从头开始,如果对象池极大,且先前的对象仍然处于激活状态,我们将需要大量时间用来无谓的遍历,导致卡顿。因此,在代码中记录之前使用的对象序号,并从序号记录的下一个对象开始查找可用对象。

  这一方法可以极大程度改善因遍历而浪费的机能、时间,对游戏性能进行优化。

  对象池是Unity中对性能优化极为重要的技术。在CPU、内存并非充满"Power"的情况下,对象池是让硬件的无谓重复尽可能降到最低,使有限的硬件资源用在最需要的地方,达到优化效果。

  个人看来,对象池最大的优点在于复用、预载这两方面。复用是对象池的典型特征、灵魂所在;而预载方面,作为玩家试想一下,玩家是愿意在加载界面多花1秒钟,还是在激烈战斗时突然卡顿0.1秒。结果是显而易见的。

相关文章

OKR与自驱力的关系是什么?

OKR与自驱力的关系是什么?

2023-10-14
office是什么软件类型?

office是什么软件类型?

2023-10-14
Cloud-IDE 是什么?

Cloud-IDE 是什么?

2023-10-14
主机和端系统之间有什么不同?

主机和端系统之间有什么不同?

2023-10-14

最新文章

常见网络安全面试题:Windows常用的命令有哪些?

常见网络安全面试题:Windows常用的命令有哪些?

2023-10-09
常见网络安全面试题:根据设备告警如何展开排查?

常见网络安全面试题:根据设备告警如何展开排查?

2023-10-09
常见网络安全面试题:mysql加固呢?(数据库加固)

常见网络安全面试题:mysql加固呢?(数据库加固)

2023-10-09
常见网络安全面试题:windows和linux加固?(操作系统加固)

常见网络安全面试题:windows和linux加固?(操作系统加固)

2023-10-09
在线咨询 免费试学 教程领取