0

I found a great object pooling script but it's in UnityScript and my project is in C#. I've been trying to convert it but I'm stuck on one error that I don't quite understand. Here is my script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class EasyObjectPool : MonoBehaviour {
    private class PoolInfo{

    public string poolName;
    public GameObject prefab;
    public int poolSize;
    public bool canGrowPoolSize = true;

}

private class Pool{

    private List<PoolObject> list = new List<PoolObject>();
    public bool  canGrowPoolSize;

    public void  Add (PoolObject poolObject){
        list.Add(poolObject);
    }

    public int Count (){
        return list.Count;
    }


    public GameObject ObjectAt ( int index  ){

        PoolObject result;
        if(index < list.Count) {
            result = list[index];
        }

        return result;

    }
}
static public EasyObjectPool instance ;
PoolInfo[] poolInfo;

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

}

The error is: "Cannot implicitly convert type 'UnityEngine.GameObject' to `PoolObject'"

for lines:

PoolObject currentObject = pool.ObjectAt(index);

and

return poolObject;

This script references another script called PoolObject but it doesn't give me any errors so I didn't figure it was related to these errors. Here is that script:

using UnityEngine;
using System.Collections;

public class PoolObject : MonoBehaviour {

[HideInInspector]
public bool availableForReuse = true;


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



}
}

Anyone tell me what I'm doing wrong here?

user3776884
  • 85
  • 2
  • 7
  • Which one is line 106 and 144? Post the code on those lines. – apxcode Jun 25 '14 at 20:55
  • Sorry, I didn't know this code function didn't number the lines. I edited my question – user3776884 Jun 25 '14 at 21:02
  • Is `PoolObject` another class that you didn't paste above? – apxcode Jun 25 '14 at 21:07
  • It's the name of the script that actually instantiates the objects but it doesn't give me any errors so I didn't figure it was related. I updated my question again with that script. – user3776884 Jun 25 '14 at 21:37
  • Yeah, that is what I thought. My answer below should fix your problems. Good luck on your game! – apxcode Jun 25 '14 at 22:06
  • That got rid of the two errors but another one has popped up: – user3776884 Jun 25 '14 at 23:02
  • "Use of unassigned local variable 'result'" – user3776884 Jun 25 '14 at 23:04
  • For the line: "return result; " in ObjectAt – user3776884 Jun 25 '14 at 23:05
  • @user3776884 Oh that one is easy. Check what I did to result down in my updated answer. – apxcode Jun 26 '14 at 03:30
  • Ya, that is pretty obvious now that I look at it LOL, thanks. No more errors but I'm getting a warning "Field 'EasyObjectPool.poolInfo' is never assigned to, and will always have its default value 'null'" – user3776884 Jun 26 '14 at 04:05
  • For: "PoolInfo[] poolInfo;" and for my public variables poolName, prefab, and poolSize and these variables also don't show up in the inspector as they should. I'm assuming there's something wrong with the PoolInfo class? – user3776884 Jun 26 '14 at 04:08
  • @user3776884 If it is private then it won't show up in the inspector. If you have any more questions you can post a new questions to narrow down the problems easier on that post. – apxcode Jun 26 '14 at 05:07
  • Alrighty, thanks you did fix my initial errors. Really appreciate all the help – user3776884 Jun 26 '14 at 05:17

2 Answers2

0

Problem 1

In the function GetObjectFromPool() you are trying to return a GameObject but in reality you are giving it a PoolObject.

So change this line:

public GameObject GetObjectFromPool(string poolName)
{
...
}

To this:

public PoolObject GetObjectFromPool(string poolName)
{
...
}

Now you are returning a PoolObject type.

Problem 2

The same happens in ObjectAt

public GameObject ObjectAt(int index)
{           
    PoolObject result = null;

    if(index < list.Count)
       result = list[index];

    return result;      
}

Just swap GameObject for PoolObject again and you are done.


Foreseeable Future Problem

There is going to be another class that calls GetObjectFromPool(), so make sure that if that class needs a GameObject you take the gameObject component from the PoolObject.

apxcode
  • 7,696
  • 7
  • 30
  • 41
-1

pool.ObjectAt returns a GameObject, not the attached component of type PoolObject.

Change ObjectAt to this:

public PoolObject ObjectAt ( int index  ){

    PoolObject result;
    if(index < list.Count) {
        result = list[index];
    }

    return result;

}
Tyler Kendrick
  • 418
  • 6
  • 18