Проблема с механизмом пула объектов, очередь, содержащая пул, не может быть статической, поскольку статические переменные не наследуются - PullRequest
0 голосов
/ 04 июля 2019

Я устанавливаю механизм объединения объектов в единстве, в основном он работает следующим образом: у вас есть базовый абстрактный класс с именем «Poolable», со статической очередью, содержащей объекты (в данном случае GameObjects), есть классназывается Projectile, который наследуется от Poolable, поскольку это то, что я сейчас хочу объединить.Кроме того, он распространяется на класс Bullet, который наследуется от Projectile, но проблема в том, что если бы у меня был класс Arrow, который наследовал от Projectile, он бы использовал тот же пул, потому что пул статичен внутри 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()
    {
    }
}

Ответы [ 2 ]

0 голосов
/ 05 июля 2019

Если я не ошибаюсь, ваш пул объектов должен быть однородным.Это означает, что ваш пул содержит только один тип объекта.Например, вы не хотите, чтобы arrow и bullet совместно использовали один и тот же пул, даже если они все projectiles.У нас нет c ++ decltype в c #, поэтому, если вы хотите, чтобы у вашего объекта была нестатическая функция-член 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);
    }
}
0 голосов
/ 04 июля 2019

Вы должны посмотреть на шаблон Singleton. Трудно предложить подходящую реализацию для того, что вам нужно, потому что я не знаю, что вы хотите с ней сделать, но в принципе вы можете добавить что-то подобное в свой класс:

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.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...