That’s kind of the best way to describe my problem, I guess. I found a great object pool that was in JS and with help here I managed to convert it to C#. The pool works, it creates the pool for the specified amount of projectiles and spawns them in the heirarchy deactivated but only one object will be used.
The projectile is scripted to deactivate on collision and spawn a particle effect. The first time I fire a projectile, it does this as intended. But every time after that I fire, the projectile will ignore collisions and keep moving forward. Firing again will only reset that object’s position back to the scripted launch position, but it will still ignore collisions. If I fire the first projectile, and fire again while it is still moving, that projectile will just reset its position but still collide. It will not collide after.
Basically, a second projectile is never activated from the pool. It’s only resetting the first projectile. So, I’m a bit confused why it’s doing this. Four scripts are doing this, so I hope it’s not too much to read through and I greatly appreciate any help.
The object pooling scripts:
public class EasyObjectPool : MonoBehaviour {
[System.Serializable]
public class PoolInfo{
[SerializeField]
public string poolName;
public GameObject prefab;
public int poolSize;
public bool canGrowPoolSize = true;
}
[System.Serializable]
public class Pool{
public List<PoolObject> list = new List<PoolObject>();
public bool canGrowPoolSize;
public void Add (PoolObject poolObject){
list.Add(poolObject);
}
public int Count (){
return list.Count;
}
public PoolObject ObjectAt ( int index ){
PoolObject result = null;
if(index < list.Count) {
result = list[index];
}
return result;
}
}
static public EasyObjectPool instance ;
[SerializeField]
PoolInfo[] poolInfo = null;
private Dictionary<string, Pool> poolDictionary = new Dictionary<string, Pool>();
void Start () {
instance = this;
CheckForDuplicatePoolNames();
CreatePools();
}
private void CheckForDuplicatePoolNames() {
for (int index = 0; index < poolInfo.Length; index++) {
string poolName= poolInfo[index].poolName;
if(poolName.Length == 0) {
Debug.LogError(string.Format("Pool {0} does not have a name!",index));
}
for (int internalIndex = index + 1; internalIndex < poolInfo.Length; internalIndex++) {
if(poolName == poolInfo[internalIndex].poolName) {
Debug.LogError(string.Format("Pool {0} & {1} have the same name. Assign different names.", index, internalIndex));
}
}
}
}
private void CreatePools() {
foreach(PoolInfo currentPoolInfo in poolInfo){
Pool pool = new Pool();
pool.canGrowPoolSize = currentPoolInfo.canGrowPoolSize;
for(int index = 0; index < currentPoolInfo.poolSize; index++) {
//instantiate
GameObject go = Instantiate(currentPoolInfo.prefab) as GameObject;
PoolObject poolObject = go.GetComponent<PoolObject>();
if(poolObject == null) {
Debug.LogError("Prefab must have PoolObject script attached!: " + currentPoolInfo.poolName);
} else {
//set state
poolObject.ReturnToPool();
//add to pool
pool.Add(poolObject);
}
}
Debug.Log("Adding pool for: " + currentPoolInfo.poolName);
poolDictionary[currentPoolInfo.poolName] = pool;
}
}
public PoolObject GetObjectFromPool ( string poolName ){
PoolObject poolObject = null;
if(poolDictionary.ContainsKey(poolName)) {
Pool pool = poolDictionary[poolName];
//get the available object
for (int index = 0; index < pool.Count(); index++) {
PoolObject currentObject = pool.ObjectAt(index);
if(currentObject.AvailableForReuse()) {
//found an available object in pool
poolObject = currentObject;
break;
}
}
if(poolObject == null) {
if(pool.canGrowPoolSize) {
Debug.Log("Increasing pool size by 1: " + poolName);
foreach (PoolInfo currentPoolInfo in poolInfo) {
if(poolName == currentPoolInfo.poolName) {
GameObject go = Instantiate(currentPoolInfo.prefab) as GameObject;
poolObject = go.GetComponent<PoolObject>();
//set state
poolObject.ReturnToPool();
//add to pool
pool.Add(poolObject);
break;
}
}
} else {
Debug.LogWarning("No object available in pool. Consider setting canGrowPoolSize to true.: " + poolName);
}
}
} else {
Debug.LogError("Invalid pool name specified: " + poolName);
}
return poolObject;
}
}
And:
public class PoolObject : MonoBehaviour {
[HideInInspector]
public bool availableForReuse = true;
public void Activate () {
availableForReuse = false;
gameObject.SetActive(true);
}
public void ReturnToPool () {
gameObject.SetActive(false);
availableForReuse = true;
}
public bool AvailableForReuse () {
//true when isAvailableForReuse & inactive in hierarchy
return availableForReuse && (gameObject.activeInHierarchy == false);
}
}
My shoot script:
public class ShootScript : MonoBehaviour {
public PoolObject poolObject;
private Transform myTransform;
private Transform cameraTransform;
private Vector3 launchPosition = new Vector3();
public float fireRate = 0.2f;
public float nextFire = 0;
// Use this for initialization
void Start () {
string poolName= "Projectile";
poolObject = EasyObjectPool.instance.GetObjectFromPool(poolName);
}
void OnEnable () {
myTransform = transform;
cameraTransform = myTransform.FindChild("BulletSpawn");
}
void Update () {
if(Input.GetButton("Fire1") && Time.time > nextFire){
nextFire = Time.time + fireRate;
launchPosition = cameraTransform.TransformPoint(0, 0, 0.2f);
poolObject.Activate();
poolObject.transform.position = launchPosition;
poolObject.transform.rotation = Quaternion.Euler(cameraTransform.eulerAngles.x + 90, myTransform.eulerAngles.y, 0);
}
}
}
Projectile script:
public class BulletScript : MonoBehaviour {
public GameObject hitEffect;
private Transform myTransform;
public float bulletSpeed = 0.1f;
private bool spent = false;
private RaycastHit hit;
public float rayRange = 1.5f;
// Use this for initialization
void OnEnable () {
myTransform = transform;
}
// Update is called once per frame
void Update () {
myTransform.Translate(Vector3.up * bulletSpeed * Time.deltaTime);
if(Physics.Raycast(myTransform.position, myTransform.up, out hit, rayRange)&&
spent == false){
if(hit.transform.tag == "Floor"){
GameObject newHitEffect = (GameObject)Instantiate(hitEffect, hit.point, Quaternion.identity);
Destroy(newHitEffect, 2);
spent = true;
GetComponent<PoolObject>().ReturnToPool();
}
}
}
}