The implementation of the pooler for enemy unit's. In addition to it becoming a singelton, it also overrides the the abstract class so that it can: properly set the stats of the created unit,
reset unit's hp to full when spawning, keep track of it's spawned unit's count.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ObjectPooling
{
/// <summary>
/// A class that is used to pool <see cref="Enemy"/>'s.
/// </summary>
public class EnemyPooler : ObjectPoolerBase<EnemyType>
{
/// <summary>
/// A list of templates <see cref="EnemyPoolItem"/> by which we populate the pool.
/// </summary>
[SerializeField]
private List<EnemyPoolItem> enemyPoolItems;
/// <summary>
/// The shared instanced of this object.
/// </summary>
public static EnemyPooler SharedInstance;
/// <summary>
/// Dictionary storing information on the number of enemy's that are active.
/// </summary>
private Dictionary<EnemyType, int> pooledEnemyCount = new Dictionary<EnemyType, int>();
/// <summary>
/// Storing the instance.
/// </summary>
private void Awake()
{
if (SharedInstance != null)
{
Debug.LogError("Multiple instances of EnemyPooler exist");
}
SharedInstance = this;
foreach (EnemyPoolItem enemyPoolItem in enemyPoolItems)
{
itemsToPool.Add(enemyPoolItem);
}
}
/// <summary>
/// Do we have any <see cref="Enemy"/> outside of the pool.
/// </summary>
/// <returns> True if we do, otherwise false. </returns>
public bool AnyEnemysSpawned()
{
bool value = false;
foreach (int count in pooledEnemyCount.Values)
{
if (count > 0) value = true;
}
return value;
}
/// <summary>
/// In addition to <see cref="ObjectPoolerBase{T}.PopulateDictionarys(ObjectPoolBase{T}, GameObject, Queue{GameObject})"/> we populate the
/// <see cref="pooledEnemyCount"/> dictionary.
/// </summary>
/// <param name="item"> The item for <see cref="ObjectPoolerBase{T}.poolItemDictionary"/>.</param>
/// <param name="poolParent"> The transform that is the parent of instantiated objects for <see cref="ObjectPoolerBase{T}.pooledObjectsParents"/>. </param>
/// <param name="pool"> The pool for <see cref="ObjectPoolerBase{T}.pooledObjectsQueue"/>. </param>
protected override void PopulateDictionarys(ObjectPoolBase<EnemyType> item, GameObject poolParent, Queue<GameObject> pool)
{
base.PopulateDictionarys(item, poolParent, pool);
EnemyType type = item.ReturnType();
pooledEnemyCount.Add(type, 0);
}
/// <summary>
/// In addition to <see cref="ObjectPoolerBase{T}.SpawnFromPool(T, Vector3, Quaternion, Transform)"/> we reset the hp of the <see cref="Enemy"/>
/// and increment the correct value in <see cref="pooledEnemyCount"/>.
/// </summary>
/// <param name="poolType"> Type of the object that is pooled. </param>
/// <param name="position"> The local position it gets spawned in. </param>
/// <param name="rotation"> The local rotation it gets spawned in. </param>
/// <param name="parent"> The transform that will be the child of the spawned item. </param>
/// <returns> Returns the spawned object or null if the pool is empty and cant be expanded. </returns>
public override GameObject SpawnFromPool(EnemyType poolType, Vector3 position, Quaternion rotation, Transform parent)
{
GameObject enemyGO = base.SpawnFromPool(poolType, position, rotation, parent);
enemyGO.GetComponent<Enemy>().ResetHP();
pooledEnemyCount[poolType]++;
return enemyGO;
}
/// <summary>
/// In addition to <see cref="ObjectPoolerBase{T}.ReturnToPool(T, GameObject)"/> we decrement the correct value in <see cref="pooledEnemyCount"/>.
/// </summary>
/// <param name="poolType"> Pool type of the object. </param>
/// <param name="gameObject"> The object that is returning. </param>
public override void ReturnToPool(EnemyType poolType, GameObject gameObject)
{
base.ReturnToPool(poolType, gameObject);
pooledEnemyCount[poolType]--;
}
/// <summary>
/// In addition to <see cref="ObjectPoolerBase{T}.InstantiateObjectToPool(Queue{GameObject}, ObjectPoolBase{T}, Transform)"/> we instantiate a new
/// <see cref="ScriptableEnemy"/> for the instantiated <see cref="Enemy"/> and populate correctly.
/// </summary>
/// <param name="pool"> The pool the instantiated object will be added to. </param>
/// <param name="item"> The <see cref="ObjectPoolBase{T}"/> item that is used as a template for instantiation. </param>
/// <param name="parent"> The parent transform that will hold the instantiated object in the hierarchy. </param>
/// <returns> The instantiated game object. </returns>
protected override GameObject InstantiateObjectToPool(Queue<GameObject> pool, ObjectPoolBase<EnemyType> item, Transform parent)
{
GameObject obj = base.InstantiateObjectToPool(pool, item, parent);
EnemyPoolItem enemyPoolItem = item as EnemyPoolItem;
Enemy enemy = obj.GetComponent<Enemy>();
ScriptableEnemy scriptable = (ScriptableEnemy)Instantiate(enemyPoolItem.scriptableEnemy);
enemy.SetScriptableEnemy(scriptable);
return obj;
}
}
}