With the help of the smart people here, I have an object pooling script converted from JS to C#. There are some final warnings though preventing the important fields from showing up in the inspector.
Here is the script:
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 PoolObject ObjectAt ( int index ){
PoolObject result = null;
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 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;
}
}
For my public variables, I get the warning posted in the question topic: Field is never assigned to and will always have its default value. Changing the PoolInfo class from private to public fixes those warnings but the JS script has this class as private class PoolInfo extends System.Object {
. Does JS treat private and public classes differently than C#?
For line 37 I get the warning: “Field ‘EasyObjectPool.poolInfo’ is never assigned to, and will always have its default value ‘null’” and I don’t know how to fix that. Any advice?
Here is the JS version if it will help:
#pragma strict
import System.Collections.Generic;
///Private classes
private class PoolInfo extends System.Object {
public var poolName : String;
public var prefab : GameObject;
public var poolSize : int;
public var canGrowPoolSize : boolean = true;
}
private class Pool extends System.Object {
private var list : List.<PoolObject> = new List.<PoolObject>();
public var canGrowPoolSize : boolean;
public function Add(poolObject : PoolObject) {
list.Add(poolObject);
}
public function Count() : int {
return list.Count;
}
public function ObjectAt(index : int) : PoolObject {
var result : PoolObject;
if(index < list.Count) {
result = list[index];
}
return result;
}
}
//end of private classes
/// Object pooling implementation
static var instance : EasyObjectPool;
var poolInfo : PoolInfo[];
//mapping of pool name vs list
private var poolDictionary : Dictionary.<String, Pool> = new Dictionary.<String, Pool>();
function Start () {
//set instance
instance = this;
//check for duplicate names
CheckForDuplicatePoolNames();
//create pools
CreatePools();
}
private function CheckForDuplicatePoolNames() {
for (var index : int = 0; index < poolInfo.Length; index++) {
var poolName = poolInfo[index].poolName;
if(poolName.Length == 0) {
Debug.LogError(String.Format("Pool {0} does not have a name!",index));
}
for (var internalIndex : int = 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 function CreatePools() {
for (var currentPoolInfo in poolInfo) {
var pool : Pool = new Pool();
pool.canGrowPoolSize = currentPoolInfo.canGrowPoolSize;
for(var index : int = 0; index < currentPoolInfo.poolSize; index++) {
//instantiate
var go : GameObject = Instantiate(currentPoolInfo.prefab);
var 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);
//add to mapping dict
poolDictionary[currentPoolInfo.poolName] = pool;
}
}
/* Returns an available object from the pool
OR
null in case the pool does not have any object available & can grow size is false.
NOTE: The caller must activate this object by calling the Activate() method before
attempting to get another object from same pool.
*/
function GetObjectFromPool(poolName : String) : PoolObject {
var poolObject : PoolObject;
if(poolDictionary.ContainsKey(poolName)) {
var pool : Pool = poolDictionary[poolName];
//get the available object
for (var index : int = 0; index < pool.Count(); index++) {
var currentObject : PoolObject = pool.ObjectAt(index);
if(currentObject.IsAvailableForReuse()) {
//found an available object in pool
poolObject = currentObject;
break;
}
}
//scenario when no available object is found in pool
if(poolObject == null) {
if(pool.canGrowPoolSize) {
Debug.Log("Increasing pool size by 1: " + poolName);
//find the prefab for this poolname
for (var currentPoolInfo in poolInfo) {
if(poolName == currentPoolInfo.poolName) {
var go : GameObject = Instantiate(currentPoolInfo.prefab);
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;
}