Hello everyone!
I have a problem with pooling system that I’m doing. Short version of the problem is, when I try to instantiate object that I receive from scriptable object with Object.Instantiate, I get an InvalidCastException from it.
Here is the code that throws the error on line 17:
public class ObjectPool<T> where T : PooledObject
{
private int _amountToPool = 20;
private T _objectToPool;
private readonly List<T> _pool = new();
private Transform _parentTransform = null;
public ObjectPool(T initialObjectToPool, Transform parentTransform)
{
_parentTransform = parentTransform;
_pool.Clear();
_objectToPool = initialObjectToPool;
for (int i = 0; i < _amountToPool; i++)
{
var obj = Object.Instantiate(_objectToPool, _parentTransform);
obj.gameObject.SetActive(false);
_pool.Add(obj);
}
}
public T GetPooledObject()
{
var pooledObject = _pool.Where(x => !x.gameObject.activeSelf).FirstOrDefault();
if (pooledObject != null)
{
return pooledObject;
}
else
{
var obj = Object.Instantiate(_objectToPool, _parentTransform);
obj.gameObject.SetActive(false);
_pool.Add(obj);
Debug.LogWarning($"Pool {_parentTransform.name} exceeded limit! New amount pooled: {_pool.Count}");
return obj;
}
}
}
PooledObject is just an empty MonoBehaviour class for now that is inherited by each entity that i want to pool (Projectiles, enemies, …). Inheritance for enemies follows like this: EnemyName → Enemy → PooledObject → MonoBehaviour
Object pool is created by Enemy pool script, that has reference to _enemyData as scriptable object:
public class EnemyPool : MonoBehaviour
{
[SerializeField]
private Transform _playerTransform;
[SerializeField]
private EnemyData _enemyData;
private EnemyType _currentEnemy = EnemyType.None;
private ObjectPool<Enemy> _enemyPool;
public void InitializeEnemyPool(EnemyType initialEnemy)
{
_currentEnemy = initialEnemy;
Enemy objectToPool = _enemyData.GetEnemyInfo(initialEnemy);
_enemyPool = new(objectToPool, transform);
}
}
EnemyData class looks like this:
using System;
using System.Linq;
using UnityEngine;
public enum EnemyType
{
None = 0,
Goblin = 1,
Wolf = 2
}
[Serializable]
public class EnemyDataEntry
{
public EnemyType Type;
public Enemy Object;
}
[CreateAssetMenu]
public class EnemyData : ScriptableObject
{
[SerializeField]
private EnemyDataEntry[] _enemyPrefabs;
public Enemy GetEnemyInfo(EnemyType enemy)
{
var entry = _enemyPrefabs.Where(x => x.Type == enemy).FirstOrDefault();
if (entry == null)
Debug.LogError($"Enemy you are trying to get does not exist {enemy}");
return entry.Object;
}
}
Here is also a screenshot of an actual error that i get:
Funny enough, if I reference prefab of an enemy (ie. Goblin) in EnemyPool directly via SerializeField and try to make pool out of it, it works like a charm, so the problem occurs only when i try to instantiate prefabs that i receive from scriptable object.
Thank you all in advance for your answers ![]()
