C# 对象池机制出现问题,包含池的队列可能';不要是静态的,因为静态变量是';t遗传

C# 对象池机制出现问题,包含池的队列可能';不要是静态的,因为静态变量是';t遗传,c#,oop,unity3d,C#,Oop,Unity3d,我正在unity中设置一个对象池机制,其工作原理如下: 您有一个名为“Poolable”的基本抽象类,其中有一个包含对象的静态队列(在本例中为GameObjects),还有一个名为Sproject的类,它继承自Poolable,因为这就是我当前希望合并的对象。它进一步扩展到一个从Sproject继承的Bullet类,但问题是,如果我有一个从Sproject继承的Arrow类,它将使用相同的池,因为池在Poolable内部是静态的。有人知道我可以解决这个问题的方法吗 我想让它成为非静态的,但是对象

我正在unity中设置一个对象池机制,其工作原理如下: 您有一个名为“Poolable”的基本抽象类,其中有一个包含对象的静态队列(在本例中为GameObjects),还有一个名为Sproject的类,它继承自Poolable,因为这就是我当前希望合并的对象。它进一步扩展到一个从Sproject继承的Bullet类,但问题是,如果我有一个从Sproject继承的Arrow类,它将使用相同的池,因为池在Poolable内部是静态的。有人知道我可以解决这个问题的方法吗

我想让它成为非静态的,但是对象不会知道池,他们会知道自己的池。与接口相同,但它们不接受非属性的变量 我目前看到的唯一修复方法是将其添加到我使用池的每个脚本中,但这就破坏了继承的全部目的,因为我试图创建一个多态结构,其中有多个池表、多个投射,可能有多个项目符号/箭头

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()
    {
    }
}
public抽象类Poolable:monobhavior
{
受保护的静态队列objPool=new Queue();//不起作用,因为每个可池对象将仅使用此池
[SerializeField]受保护的游戏对象预制;
公共游戏对象Get()
{
if(objPool.Count==0)
{
AddObjects();
}
返回objPool.Dequeue();
}
受保护的void returntopol(游戏对象retObj)
{
objPool.Enqueue(retObj);
retObj.SetActive(假);
}
AddObjects()
{
}
}

您应该研究单例模式。很难为您需要的内容推荐合适的实现,因为我不知道您想用它做什么,但基本上,您可以向类中添加类似的内容:

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;
    }

}
之后,要么将构造函数设置为private/protected,要么确保始终使用
Poolable.instance
获取实例


希望有帮助

如果我没有弄错的话,您需要对象池是同质的。这意味着您的池只包含一种类型的对象。例如,您不希望
arrow
bullet
共享同一个池,即使它们都是
投射物。我们在c#中没有c++的
decltype
,因此,如果希望对象具有非静态成员函数
returntopol
,则必须将类型求值推迟到运行时(使用类型字典)。以下是可能满足您需要的代码:

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);
    }
}
使用System.Collections.Generic;
使用UnityEngine;
使用制度;
公共抽象类可共用:MonoBehavior
{
私有静态字典objPool
=新字典();
/// 
///从池中获取对象;如果失败,请使用替代方法创建一个对象
/// 
/// 
/// 
/// 
公共静态T Get(Func alternativeCreate),其中T:Poolable
{
if(objPool.TryGetValue(typeof(T),out var queue)&&queue.Count>0)
{
var ret=queue.Dequeue()作为T;
反应性;
返回ret;
}
返回alternativeCreate();
}
/// 
///将对象返回到池中
/// 
白杨木()
{
if(this.Reset())
{
var type=this.GetType();
排队;
if(objPool.TryGetValue(类型,输出队列))
{
排队。排队(这个);
}
其他的
{
队列=新队列();
排队。排队(这个);
添加(类型,队列);
}
}
}
/// 
///重置对象,使其准备好进入对象池
/// 
///重置是否成功。
受保护的虚拟布尔重置()
{
this.gameObject.SetActive(false);
返回true;
}
/// 
///在对象离开对象池时对其进行反应
/// 
受保护的虚拟无效重新激活()
{
this.gameObject.SetActive(true);
}
}

如果您的类是泛型的-
可池化的
可池化的
,等等,那么静态成员对于这些类型中的每一个都是唯一的。@Scott:泛型类型对于该类型使用的每个类型参数都会有不同的具体字段。但是,它没有解决多态性方面的问题。也就是说,由于
Arrow
继承了
投射物
,基类将是
可池化的
,而不是
可池化的
,从而破坏了特定类型字段的点。
射弹
池仍然会被共享,例如
箭头
子弹
不幸的是,我不太理解您的代码示例。您有一个静态池,但是您的
Get()
方法是非静态的。因此,当您调用它时,您手中已经有了所需类型的对象。这有什么意义?对于如何检索新对象,最好有一个更真实的说明。似乎更可能在某个地方有一个静态访问器,因此需要一些指定类型的方法。如果是这样的话,我认为一个简单的池字典(类型是键)就可以了。可以使用泛型方法来指定类型。但这只是一个想法,在您的情况下是否可行取决于更广泛的情况,您尚未分享。请详细说明您的问题,使其更清晰、更受约束、更不宽泛。另一个问题是您希望通过使池代码本身具有多态性来获得什么。这与上面的一点有关,即“您已经拥有所需类型的对象”。在Unity3d中有许多如何进行对象池的示例,通常它们根据对象所基于的预设来组织池。然后