【Unity】对象池技术

2023-12-24 23:38:05

【Unity】对象池技术

1.简介

对象池(Object Pooling)技术是一种用于优化游戏性能和内存管理的技术。
对象池可以用于各种需要频繁实例化和销毁游戏对象的场景,例如子弹、敌人、玩家等。其主要目标是减少频繁的内存分配和垃圾回收的次数,提高游戏的运行效率,从而提高性能和降低延迟。
在对象池中查找池中隐藏的游戏对象,将其显示出来,以避免一直实例化新的游戏对象,导致游戏性能受到影响。

2.实现

一般地,游戏会需要频繁实例化多种预制体,所以需要先将每种预制体存在各个小池中,接着通过大池进行管理,之后直接从大池中拿取和放回。

小池子(SubPool)代码

using UnityEngine;
using System.Collections.Generic;

public class SubPool
{
    //预制体
    private GameObject m_prefab;
    //父对象
    private Transform m_parent;
    //小池中所有存在场景的对象
    private List<GameObject> m_objects = new List<GameObject>();
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="parent">父对象</param>
    /// <param name="prefab">预制体</param>
    public SubPool(Transform parent, GameObject prefab)
    {
        m_parent = parent;
        m_prefab = prefab;
    }
    /// <summary>
    /// 预制体名字
    /// </summary>
    public string Name
    {
        get
        {
            return m_prefab.name;
        }
    }
    /// <summary>
    /// 生成
    /// </summary>
    /// <returns>生成的对象</returns>
    public GameObject Spawn()
    {
        GameObject go = null;
        foreach(GameObject obj in m_objects)
        {
            if (!obj.activeSelf)
            {
                go = obj;
                break;
            }
        }
        if(go == null)
        {
            go = GameObject.Instantiate(m_prefab);
            go.transform.parent = m_parent;
            m_objects.Add(go);
        }
        go.SetActive(true);
        return go;
    }
    /// <summary>
    /// 是否存在小池中
    /// </summary>
    /// <param name="go">判断的对象</param>
    /// <returns></returns>
    public bool Contains(GameObject go)
    {
        return m_objects.Contains(go);
    }
    /// <summary>
    /// 回收
    /// </summary>
    /// <param name="go">回收的对象</param>
    public void UnSpawn(GameObject go)
    {
        if(Contains(go))
        {
            go.SetActive(false);
        }
    }
    /// <summary>
    /// 回收全部
    /// </summary>
    public void UnSpawnAll()
    {
        foreach(GameObject obj in m_objects)
        {
            UnSpawn(obj);
        }
    }
}

大池子(ObjectPool)代码

using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : MonoBehaviour 
{
    //存放预制体的文件名
    public string FileName = "prefab";
    //名字-小池子字典
    private Dictionary<string, SubPool> m_pools = new Dictionary<string, SubPool>();
    /// <summary>
    /// 生成
    /// </summary>
    /// <param name="name">名字</param>
    /// <param name="parent">父对象</param>
    /// <returns>生成的对象</returns>
    public GameObject Spawn(string name, Transform parent)
    {
        SubPool pool = null;
        if(!m_pools.ContainsKey(name))
        {
            RegisterNewPool(name, parent);
        }
        pool = m_pools[name];
        return pool.Spawn();
    }
    /// <summary>
    /// 注册新的小池子
    /// </summary>
    /// <param name="name">名字</param>
    /// <param name="parent">父对象</param>
    private void RegisterNewPool(string name, Transform parent)
    {
        string path = FileName + "/" + name;
        GameObject go = Resources.Load<GameObject>(path);
        if(go != null)
        {
            SubPool pool = new SubPool(parent, go);
            m_pools.Add(pool.Name, pool);
        }
        else
        {
            Debug.Log("未找到" + path + "的预制体");
        }
    }
    /// <summary>
    /// 回收
    /// </summary>
    /// <param name="go">被回收的游戏对象</param>
    public void UnSpawn(GameObject go)
    {
        SubPool pool = null;
        foreach(SubPool p in m_pools.Values)
        {
            if(p.Contains(go))
            {
                pool = p;
                break;
            }
        }
        if(pool != null)
        {
            pool.UnSpawn(go);
        }
    }
    /// <summary>
    /// 回收全部
    /// </summary>
    public void UnSpawnAll()
    {
        foreach(SubPool p in m_pools.Values)
        {
            p.UnSpawnAll();
        }
    }
}

因为作者精力有限,文章中难免出现一些错漏,敬请广大专家和网友批评、指正。

文章来源:https://blog.csdn.net/qq_46051312/article/details/135188264
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。