对象池机制出现问题,包含池的队列不能是静态的,因为静态变量不是继承的



我正在设置一个统一的对象池机制,基本上是它的工作方式:您有一个名为"池"的基本抽象类,其中包含其中包含对象的静态队列(在本例中(,有一个称为弹丸的类,它是从池上继承的,因为这是我当前想要汇总的。它进一步扩展到了从弹丸继承的子弹等级,但是问题是,如果我有一个从弹丸继承的箭头类,它将使用同一池,因为池是静态的,可以池水内部。有人知道我可以解决这个问题的方法吗?

我考虑过将其变为静态,但随后对象不知道池,他们会知道自己的池。与接口相同,但它们不接受不是属性的变量我看到的唯一当前修复程序是将其添加到我使用池的每个脚本中,但是当我试图制作一个类似多态性的结构时,这就打破了继承的全部目的,在该结构中,您将拥有多个泳池,多个弹丸,也许多个子弹/箭头?

public abstract class Poolable : MonoBehaviour
{
    protected static Queue<GameObject> objPool = new Queue<GameObject>(); // doesn't work because every poolable object will use this pool only
    [SerializeField] protected GameObject prefab;
    public GameObject Get()
    {
        if(objPool.Count == 0)
        {
            AddObjects();
        }
        return objPool.Dequeue();
    }
    protected void ReturnToPool(GameObject retObj)
    {
        objPool.Enqueue(retObj);
        retObj.SetActive(false);
    }
    AddObjects()
    {
    }
}

如果我没记错的话,您需要对象池均匀。这意味着您的池仅包含一种类型的对象。例如,即使它们都是projectiles,您也不希望arrowbullet共享同一池。我们在C#中没有C 的decltype,因此,如果您的对象具有非静态成员函数ReturnToPool,则必须将类型评估推迟到运行时(使用类型字典(。这是可能满足您需求的代码:

using System.Collections.Generic;
using UnityEngine;
using System;
public abstract class Poolable : MonoBehaviour
{
    private static Dictionary<Type, Queue<Component>> objPool
        = new Dictionary<Type, Queue<Component>>();
    /// <summary>
    /// Get an object from the pool; If fails, use the alternative method to create one
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="alternativeCreate"></param>
    /// <returns></returns>
    public static T Get<T>(Func<T> alternativeCreate) where T : Poolable
    {
        if (objPool.TryGetValue(typeof(T), out var queue) && queue.Count > 0)
        {
            var ret = queue.Dequeue() as T;
            ret.Reactive();
            return ret;
        }
        return alternativeCreate();
    }
    /// <summary>
    /// Return the object to the pool
    /// </summary>
    public void ReturnToPool()
    {
        if (this.Reset())
        {
            var type = this.GetType();
            Queue<Component> queue;
            if (objPool.TryGetValue(type, out queue))
            {
                queue.Enqueue(this);
            }
            else
            {
                queue = new Queue<Component>();
                queue.Enqueue(this);
                objPool.Add(type, queue);
            }
        }
    }
    /// <summary>
    /// Reset the object so it is ready to go into the object pool
    /// </summary>
    /// <returns>whether the reset is successful.</returns>
    protected virtual bool Reset()
    {
        this.gameObject.SetActive(false);
        return true;
    }
    /// <summary>
    /// Reactive the object as it goes out of the object pool
    /// </summary>
    protected virtual void Reactivate()
    {
        this.gameObject.SetActive(true);
    }
}

您应该研究单例模式。很难为您需要的东西建议合适的实现,因为我不知道您想处理什么,但是基本上,您可以在班级中添加类似的东西:

private static Poolable _instance;
private static object _instanceLock = new Object();
public static Poolable Instance
{
    get
    {
        if (_instance == null)
        {
            lock (_instanceLock)
            {
                if (_instance == null)
                {
                    this._instance = [Whatever way you instantiate it];
                }
            }
        }
        return _instance;
    }
}

之后,要么将构造函数私有/受保护,并确保您始终使用Poolable.Instance

希望它有帮助!

相关内容

最新更新