Unity游戏框架设计之缓存池管理器

Unity游戏框架设计之缓存池管理器

简单介绍

在游戏运行的过程中,我们可能遇到这样的需求,即创建大量相同类型的敌人。在传统方法中,我们将对每一个敌人都重新创建,但这样是效率低且占据内存的。

为此我们可以这样做,所有敌人在创建时,都从敌人缓存池中取出敌人对象,当敌人死亡时,则将敌人放回到缓存池中。这样我们可以实现对敌人对象的复用,而不是频繁的创建和销毁敌人对象。

因此,我们可以基于享元模式,开发缓存池管理器来实现上述需求。缓存池管理器为所有相同类型的对象都创建一个缓存池,如果需要在游戏中创建对象,则从缓存池中取出对象,如果需要销毁一个对象,则将对象放回到缓存池中。利用缓存池管理器,我们避免频繁进行对象的创建和销毁,从而提高执行效率并降低内存占用。

代码设计

public class CachePoolManager : SingletonMono<CachePoolManager>
{
    private readonly Dictionary<string, ObjectPool<GameObject>> _cachePoolSet = new();
    private static int _defaultMaxCapacity;

    public static void Initialize(int defaultMaxCapacity)
    {
        _defaultMaxCapacity = defaultMaxCapacity;
    }

    public void AddCachePool(string cachePoolName, GameObject asset, Transform father, int maxCapacity = default)
    {
        if (maxCapacity == default)
        {
            maxCapacity = _defaultMaxCapacity;
        }
        if (_cachePoolSet.ContainsKey(cachePoolName))
        {
            return;
        }
        _cachePoolSet.Add(cachePoolName, new(() => Instantiate(asset, father),
            OnGetInstance, OnReleaseInstance, OnDestroyInstance, false, maxCapacity, maxCapacity)
        );
    }

    public void RemoveCachePool(string cachePoolName)
    {
        if (!_cachePoolSet.ContainsKey(cachePoolName))
        {
            return;
        }
        _cachePoolSet[cachePoolName].Clear();
        _cachePoolSet.Remove(cachePoolName);
    }

    public bool ContainsCachePool(string cachePoolName)
    {
        return _cachePoolSet.ContainsKey(cachePoolName);
    }

    public GameObject GetInstance(string cachePoolName)
    {
        if (!_cachePoolSet.ContainsKey(cachePoolName))
        {
            return default;
        }
        return _cachePoolSet[cachePoolName].Get();
    }

    public void PutInstance(string cachePoolName, GameObject instance)
    {
        if (!_cachePoolSet.ContainsKey(cachePoolName))
        {
            return;
        }
        _cachePoolSet[cachePoolName].Release(instance);
    }

    private void OnGetInstance(GameObject instance)
    {
        if (instance == null)
        {
            return;
        }
        instance.SetActive(true);
    }

    private void OnReleaseInstance(GameObject instance)
    {
        if (instance == null)
        {
            return;
        }
        instance.SetActive(false);
    }

    private void OnDestroyInstance(GameObject instance)
    {
        Destroy(instance);
    }
}

代码说明

(一)基于 Unity 官方 API ObjectPool 实现。

(二)实现缓存池的创建、删除、查询操作,以及从缓存池中获取实例和放回实例的操作。

(三)每次从缓存池中获取对象时,都必须重置当前对象。比如,从缓存池中获取游戏对象后,如果需要为游戏对象添加脚本,则必须先判断脚本是否存在,如果存在则先删除此脚本,然后才重新添加脚本。

(四)每次场景被销毁后,都必须删除在当前场景创建的所有缓存池。防止下次重新进入此场景,从缓存池中取出游戏对象时发生空指针异常问题。发生的原因是,从缓存池中获取的游戏对象属于上一次被销毁的场景中的游戏对象。

后记

由于个人能力有限,文中不免存在疏漏之处,恳求大家斧正,一起交流,共同进步。

posted @ 2024-04-30 16:34  珂霖  阅读(7)  评论(0编辑  收藏  举报