【性能优化】对象池

对象池简介:

对象池优化的主要思想是重复利用已经创建的对象,避免频繁的创建和销毁。具体来说,对象池会在游戏启动时预先创建一定数量的对象,并将其存储在一个池中。当需要使用该类型的对象时,从对象池中取出一个空闲对象,而不是每次都创建一个新对象。当该对象不再使用时,将其重新放回到对象池中,以便下次继续使用。

为什么要使用对象池 O.o?

在咱们游戏开发当中,会出现很多的内存利用产生的问题,对象池就可以很好的提高性能和内存的利用率,所以对象池也是一种常见的优化手段。

对象池优点:

Unity对象池优化主要有以下几个方面的优化:

  1. 减少内存分配:对象池可以减少不必要的资源分配,从而降低了内存使用率。

  2. 减少CPU消耗:频繁的对象创建和销毁对象会导致额外的CPU消耗 使用对象池技术可以避免频繁的对象创建和销毁操作 从而减少CPU的消耗

  3. 提高代码易读性:使用对象池技术可以使我们写的代码更加清晰明了,便于后期维护和扩展。

代码实现(代码内有详细简介):

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

public class ObjTools : MonoBehaviour
{
    // 单例
    public static ObjTools poolInstance;

    // 池子要存储的物体
    public GameObject Object;
    // 内存区(队列)
    public Queue<GameObject> objectPool = new Queue<GameObject>();
    // 池子的初始容量
    public int defaultCount = 16;
    // 池子的最大容量
    public int maxCount = 25;
    private void Awake()
    {
        poolInstance = this;
        //Init();
    }

    // 对池子进行初始化(创建初始容量个数的物体)
    public void Init()
    {
        GameObject obj;
        for (int i = 0; i < defaultCount; i++)
        {
            obj = Instantiate(Object, this.transform);
            // 将生成的对象入队
            objectPool.Enqueue(obj);
            obj.SetActive(false);
            
        }
    }
    // 从池子中取出物体
    public GameObject Get()
    {
        GameObject tmp;
        // 如果池子内有物体,从池子取出一个物体
        if (objectPool.Count > 0)
        {
            // 将对象出队
            tmp = objectPool.Dequeue();
            tmp.SetActive(true);
        }
        // 如果池子中没有物体,直接新建一个物体
        else
        {
            tmp = Instantiate(Object, this.transform);
        }
        return tmp;
    }
    // 将物体回收进池子
    public void Remove(GameObject obj)
    {
        // 池子中的物体数目不超过最大容量
        if (objectPool.Count < maxCount)
        {
            // 该对象没有在队列中
            if (!objectPool.Contains(obj))
            {
                // 将对象入队
                objectPool.Enqueue(obj);
                obj.SetActive(false);
            }
        }
        // 超过最大容量就销毁
        else
        {
            Destroy(obj);
        }
    }
    
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Game : MonoBehaviour
{
    ObjTools obj;
    public GameObject game, dr;
    Queue<GameObject> queue = new Queue<GameObject>();
    private void Awake()
    {
        obj = this.GetComponent<ObjTools>();
    }
    void Start()
    {
        obj.Init();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            game = obj.Get();
            game.transform.position = transform.position + transform.forward * 2;
            game.transform.rotation = new Quaternion(0, 0, 0, 0);
            queue.Enqueue(game);
            game.transform.position = Vector3.MoveTowards(transform.position, dr.transform.position, 0.5f);
            Invoke("Del", 2);
        }
    }
    public void Del()
    {
        if (game != null)
        {
            obj.Remove(queue.Dequeue());
        }
    }

}

总结:

我上方使用的队列实现的对象池,除此之外,游戏开发中还可以使用其他数据结构来实现对象池,例如:

  1. 栈:栈是一种后进先出(LIFO)的数据结构,适用于对象池的实现。通过将对象推入栈顶和从栈顶弹出对象,可以实现对象的回收和重用。

  2. 集合:列表是一种动态数组,可以在任意位置插入、删除和访问元素。可以使用列表来保存对象,并通过标记或其他方式来跟踪哪些对象是可用的。当需要获取一个对象时,可以遍历列表找到一个可用的对象进行重用。

  3. 字典:字典是一种键值对存储的数据结构,可以使用字典来管理对象池中的对象。可以将对象的唯一ID作为键,将对象本身作为值,通过键值对来获取和回收对象。

  4. 对象池管理器:可以创建一个自定义的对象池管理器类,其中可以使用各种数据结构来实现对象池。这个管理器可以负责对象的创建、获取、回收和管理,提供接口供其他脚本调用。

需要根据具体需求来进行选择合适的数据结构来实现对象池,以满足项目的需求和性能要求。不同的实现方式可能在性能和灵活性上有所差异。

后期补充(重中之重(非技术)):

其他的工具研究的不多了  就先提供两个比较常用的调试工具叭

后期还会有其他更改与补充  十分欢迎大家来分享自己de见解 

希望能和大家相互学习 一起提升自己的芝士!!!

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值