Unity对象池

本文探讨了C#中抽象的单例基类和对象池的设计,展示了如何使用继承和静态成员实现高效管理游戏对象和组件的生命周期。实例化对象池用于复用资源,降低内存消耗,同时提供了创建、回收和清空对象的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例基类

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

public abstract class MonoSignal<T> : MonoBehaviour where T : MonoSignal<T>
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType(typeof(T)) as T;
                if (instance == null)
                {
                    instance = new GameObject("Chinar Single of " + typeof(T).ToString(),
                        typeof(T)).GetComponent<T>();
                }
            }

            return instance;
        }
    }

    private void Awake()
    {
        if (instance==null)
        {
            instance = this as T;
        }
    }

    private void OnApplicationQuit()
    {
        instance = null;
    }
}

对象池单例

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

public class ObjectPool : MonoSignal<ObjectPool>
{
    
    private Dictionary<string, List<GameObject>> cache = new Dictionary<string, List<GameObject>>();
    private int i = 0;
    
    /// <summary>
    /// 创建显示对象
    /// </summary>
    /// <returns>The object.</returns>
    /// <param name="key">对象名称</param>
    /// <param name="go">对象的预制件</param>
    /// <param name="position">对象的新位置</param>
    /// <param name="quaternion">对象的角度</param>
    public GameObject CreateObject(string key, GameObject go, Vector3 position, Quaternion quaternion)
    {
        //返回池中未激活的对象,所有都被激活就返回空,赋值给临时对象
        GameObject tempgo = cache.ContainsKey(key) ? 
            cache[key].Find(p => !p.activeSelf) : null;
        if (tempgo != null) //如果临时对象不为空
        {
            tempgo.transform.position = position;   //设置位置
            tempgo.transform.rotation = quaternion; //旋转信息
            tempgo.name = key;
        }
        else //否则,就是空了。(也就是没能从池子里取出对象)
        {
            tempgo = Instantiate(go, position, quaternion); //那就根据传入的预设物,生成一个新物体
            tempgo.name = key;
            print("实例化物体数量:" + i++);
            if (!cache.ContainsKey(key)) //池中没有键
            {
                cache.Add(key, new List<GameObject>()); //新建一个 列表
            }

            cache[key].Add(tempgo); //给字典中的列表加入/add 临时物体,如果有键就直接添加了
        }

        tempgo.SetActive(true); //并启用临时物体
        return tempgo;          //返回
    }


    /// <summary>
    /// 直接回收
    /// </summary>
    /// <param name="go">Go.</param>
    public void CollectObject(GameObject go)
    {
        go.SetActive(false);
    }


    /// <summary>
    /// 延迟回收
    /// </summary>
    /// <param name="go">Go.</param>
    /// <param name="delay">Delay.</param>
    public void CollectObject(GameObject go, float delay)
    {
        StartCoroutine(Collect(go, delay));
    }
    
    private IEnumerator Collect(GameObject go, float delay)
    {
        yield return new WaitForSeconds(delay);
        CollectObject(go);
    }
    
    /// <summary>
    /// 释放资源
    /// </summary>
    /// <returns>The clear.</returns>
    /// <param name="key">Key.</param>
    public void Clear(string key)
    {
        if (cache.ContainsKey(key))
        {
            //Destroy当中所有的对象
            for (int i = 0; i < cache[key].Count; i++)
            {
                Destroy(cache[key][i]);
            }
            //清除键当中的所有值
            //cache[key].Clear();
            //清除这个键(键值一起清除)
            cache.Remove(key);
        }
    }


    /// <summary>
    /// 释放所有对象池
    /// </summary>
    public void ClearAll()
    {
        var list = new List<string>(cache.Keys);
        for (int i = 0; i < list.Count; i++)
        {
            Clear(list[i]);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值