簡體   English   中英

如何在列表中存儲具有不同泛型的相同類型的類?

[英]How do I store the same types of classes that have a different generic inside of a list?

我一直在修補這個,我有一個“RespawnManager”,我想用它來管理具有不同泛型的多個“SpawnPoint”類,但它最終迫使我對我不想要的“RespawnManager”使用泛型.

假設我有一個SpawnPoint<T>類,我創建了一個SpawnPoint<Enemy1>SpawnPoint<Enemy2>SpawnPoint<Enemy3> 有什么辦法可以制作一個列表來管理任何通用的多個“SpawnPoint”?

基類:

public abstract class SpawnPoint<T> : MonoBehaviour
{
    //how big the range of the spawn protection is   
    public int spawnProtectionRadius = 20;
    public bool Occupied { get; set; }

    public bool IsInSpawn(Transform target) 
    {
        Debug.Log((target.position - transform.position).magnitude);
        if ((target.position - transform.position).magnitude <= spawnProtectionRadius)
        {
            return true;
        }
        return false;
    }

    public abstract T Get();
}

繼承這個的類

public class SeaMineSpawnPoint : SpawnPoint<Seamine>
{
    public override Seamine Get()
    {
        return SeaMineObjectPool.PoolInstance.Get();
    }

    private void Start()
    {
        RespawnManager<Seamine>.respawnManager.AddSpawn(this);
    }
}

重生管理員:

public class RespawnManager<T> : MonoBehaviour where T : Component
{

    public static RespawnManager<T> respawnManager;

    [SerializeField]
    private List<Transform> playerList;

    [SerializeField]
    private List<SpawnPoint<T>> spawnpoints;

    private float respawnCounter;

    private void Awake()
    {
        respawnManager = this;
    }

    private void Start()
    {
        foreach (SpawnPoint<T> sp in spawnpoints)
        {
            Debug.Log(sp.transform.position);
        }
    }

    public void AddSpawn(SpawnPoint<T> spawnPoint)
    {
        spawnpoints.Add(spawnPoint);
    }

    public void RespawnSeaMines()
    {
        if (respawnCounter > 5)
        {
            respawnCounter = 0;
            foreach (SpawnPoint<T> sp in spawnpoints)
            {
                foreach (Transform playerT in playerList)
                {

                    if (sp.Occupied == false && !sp.IsInSpawn(playerT))
                    {
                        Component ourGameObj = sp.Get();
                        ourGameObj.transform.position = sp.transform.position;
                        ourGameObj.gameObject.SetActive(true);
                        sp.Occupied = true;
                        return;
                    }
                }
            }
        }

    }

    private void Update()
    {
        respawnCounter += Time.deltaTime;
        Debug.Log(respawnCounter);
        RespawnSeaMines();
    }

}

對象池

//Class that's used for object pooling of different types.
    //'T' must be a Unity component or it will error.
    public abstract class ObjectPool<T> : MonoBehaviour where T : Component
    {
        //An object with this specific component that we use to copy.
        [SerializeField]
        private T prefab;

        //Makes sure that only 1 coroutine runs at a time
        private bool coroutineIsRunning;


        //The singleton instance to our object pool.
        public static ObjectPool<T> PoolInstance { get; private set; }

        //A queue is used to organize plus activate and deactivate objects which
        //have this component.
        protected Queue<T> objects = new Queue<T>();

        private void Awake()
        {
            //Set the instance of this pool to this class instance. Only one of these can be set.
            if (PoolInstance != null)
            {
                throw new System.Exception("Singleton already exists. Cannot make another copy of this");
            }
            PoolInstance = this;
        }


        public T Get()
        {
            //If the queue happens to be empty, then add a brand new component.
            if (objects.Count == 0) AddObjects(1);

            //Returns the generic component and removes it from the queue.
            return objects.Dequeue();
        }


        public void ReturnToPool(T objectToReturn)
        {
            //Disables the game object that the T component is attached to.
            objectToReturn.gameObject.SetActive(false);

            //Stores the T component in the queue.
            objects.Enqueue(objectToReturn);
        }

        public void AddObjects(int count)
        {
            for (int i = 0; i < count; i++)
            {
                //Create a new copy of the prefab.
                //The prefab is a game object with the T component attached to it.
                T newObject = Instantiate(prefab);

                //Disable the game object.
                newObject.gameObject.SetActive(false);

                //Add the T component to the queue.
                //The T component is attached to the game object we created earlier.
                objects.Enqueue(newObject);
            }
        }

        public T GetWithDelay(int time)
        {
            T genericToReturn = null;
            if (!coroutineIsRunning)
            {
                coroutineIsRunning = true;
                StartCoroutine(GetCoroutine(time, genericToReturn));
            }
            return genericToReturn;
        }

        private IEnumerator GetCoroutine(int time, T generic)
        {
            float counter = 0;
            while (counter < time)
            {
                counter += Time.deltaTime;
                yield return null;
            }
            generic = Get();
            generic.gameObject.SetActive(true);
            coroutineIsRunning = false;
        }
    }

你應該能夠來聲明spawnpoints財產RespawnManager作為一個List<SpawnPoint<Component>>而不是List<SpawnPoint<T>> 這將允許您完全從RespawnManager刪除<T>類型參數並使其非通用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM