Field is never assigned to, and will always have its default value

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

just assign a default value (null in this case) to get rid of the warning. However this is just a warning and shouldn’t break anything.

Depending on what you are trying to show in the inspector you may need to add [System.Serializable] over the class definitions for your classes that don’t inherit from any of the Unity stuff.

[System.Serializable]
private class PoolInfo
{
...

Or use [SerializeField] over private variables that you want to see in editor.

Or the combination of both depending on the case.

You can get rid of the warning by simply changing PoolInfo[] poolInfo; to PoolInfo[] poolInfo = null;, but i doubt that’s what’s causing the variables not to show in the inspector.

Your problem is that you declared poolInfo as a private variable and you didn’t initialize it. Since it’s private it can only be initialized by your script which you did not. In the UnityScript version it’s declared as public. In UnityScript all variables are public by default in C# all variables are private by default.

As far as i know in UnityScript you don’t need the Serializable attribute on custom classes to have them serialized. However in C# you have to mark them as serializable.

It’s strange that UnityScript does allow this. To use a local private class in a public variable usually shouldn’t work.

So my advise to fix your problems:

  • make your PoolInfo class public.
  • put the [System.Serializable] attribute on the PoolInfo class.
  • make poolInfo public as well.

Now you should see the poolInfo array in the inspector.