简体   繁体   中英

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

I've been tinkering with this and I have a 'RespawnManager' that I want to use to manage my multiple 'SpawnPoint' classes with different generics but it ended up forcing me to use generics for my 'RespawnManager' which I don't want.

Let's say I had a SpawnPoint<T> class and I made a SpawnPoint<Enemy1> , SpawnPoint<Enemy2> , and SpawnPoint<Enemy3> . Is there any way I can make a list that can just manage multiple 'SpawnPoint's of any generic?

Base class:

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

Class that Inherits this

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

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

Respawn manager:

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

}

ObjectPool

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

You should be able to declare your spawnpoints property in RespawnManager as a List<SpawnPoint<Component>> instead of List<SpawnPoint<T>> . That will allow you to get rid of the <T> type parameter entirely from RespawnManager and make it non-generic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM