千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > Unity对象池的学习

Unity对象池的学习

来源:千锋教育
发布人:wjy
时间: 2022-07-29 16:40:00 1659084000

  对象池在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秒。结果是显而易见的。

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT