- Home /
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;
}
Note that if you're having some errors, the inspector won't update. If that's the case, fix them first and then assign the poolInfo variable in the inspector.
So are you assigning a value for EasyObjectPool.poolInfo
anywhere ? That's what the warning is telling you to check.
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.
It's just a warning so it's not anything you did "wrong". If you'r code is still work in progress it's completely normal to get warnings. Warnings don't prevent you from compiling or working normally with your code in Unity/$$anonymous$$onodevelop.
There at least was a bug in earlier versions of Unity where certain problems in your code could cause all warnings to turn into errors, which would cause your problem. In this case though the warnings should show as errors in the console (red circle ins$$anonymous$$d of yellow triangle)
maybe post the original js code - there's no definition for PoolObject
it'll help people here (and StackOverflow where you've also posted) to help you
I updated my question with the JS version. PoolObject is another script but I didn't think it was related to the issue of my variables not showing up in the inspector. Here is the PoolObject script in C#:
public class PoolObject : $$anonymous$$onoBehaviour {
[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);
}
}
Here is the JS version of it:
#pragma strict
@HideInInspector var isAvailableForReuse : boolean = true;
function Activate() {
isAvailableForReuse = false;
gameObject.SetActive(true);
}
function ReturnToPool() {
gameObject.SetActive(false);
isAvailableForReuse = true;
}
function IsAvailableForReuse() : boolean {
//true when isAvailableForReuse & inactive in hierarchy
return isAvailableForReuse && (gameObject.activeInHierarchy == false);
}
Answer by AyAMrau · Jun 26, 2014 at 11:44 AM
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.
This might be part of the problem. The JS had private class PoolInfo extends System.Object
which I now know is that language's way of doing System.Serializable. So I added [System.Serializable]
above both the PoolInfo and Pool classes, as well as [SerializeField]
over my variables, but they still don't show in the inspector. I posted the JS version in my question if this will help
I copied your C# code and added System.Serializable over PoolInfo class ans SerializeField over PoolInfo[] poolInfo variable. This is what I get (you need to add elements to the array before being able to look into them):
You can't show the EasyObjectPool instance because it's static or the poolDictionary dictionary because it's also not directly supported.
Or is there something else you wanted to show?
That was it, thank you! Had to add SerializeField over PoolInfo[]
It all shows up now whether it works, dunno yet. I'll just start a new question if I have any more problems. Thanks again! And thank you to everyone else, too. I've learned a lot about UnityScript the past week lol
This method of adding [SerializeField] also worked for me whilst starting out with Unity's Roll-a-Ball Tutorial. need to add this into my code in order to be able to change the speed of the ball from the inspector rather than having to edit the script :) script attached below to show where i added this in for all the other googlers looking for a solution to this problem :D
using UnityEngine;
using System.Collections;
public class PlayerController : $$anonymous$$onoBehaviour
{
[SerializeField] //This is the line needed to fix the problem :D (For Private Variables)
private float speed; //To show this Variable in the inspector
private Rigidbody rb;
void Start ()
{
rb = GetComponent<Rigidbody> ();
}
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rb.AddForce (movement * speed);
}
}
Answer by NoseKills · Jun 26, 2014 at 09:03 AM
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.
Answer by Bunny83 · Jun 26, 2014 at 06:46 PM
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.
There is no need to make the variable public, using [SerializeField] will expose it in the editor without breaking encapsulation.
@AyA$$anonymous$$rau: Of course you can use SerializeField but it wouldn't make any sense.
The variable was public in the UnityScript version
The variable is an important interface which need to by accessed / set from outside, so making it private doesn't make any sense.
Your answer
Follow this Question
Related Questions
Field is never assigned to and will always have its default value. 0 Answers
Creation of RPG Class Stat Presets? 1 Answer
Why can't i access my c# class from javascript 1 Answer
Distribute terrain in zones 3 Answers
CSharp Classes = Scripts? Difference between private string and normal string? 1 Answer