Variable Becoming null only inside functions
Hi all,
This problem has thrown me for a loop. My code worked fine until I turned a certain object into a prefab. Now the things I instantiate in it become null exclusively inside of functions.
I have a list of Stage objects called stages. In the Awake() function I load them and set the current stage to stages[0].
void Awake()
{
stageHandler = GameObject.Find("StageHandler").GetComponent<StageHandler>();
worldID = 1;
loadStages();
setStage(stages[0]);
Debug.Log("Awake: " + stages.Count);
}
The debug line says there are 5 Stages in the list.
The Start, Update, and OnEnable functions also say there are 5.
void Start () {
Debug.Log("Start: " + stages.Count);
}
void OnEnable()
{
Debug.Log("OnEnable: " + stages.Count);
}
void Update()
{
Debug.Log("Update: " + stages.Count);
}
But as soon as I click the button to move up one stage...
public void moveUpOneStage()
{
Debug.Log("MoveUp: " + stages.Count);
int location = stages.IndexOf(currentStage);
Debug.Log(currentStage);
if(stages.Count > location)
{
setStage(stages[location + 1]);
}
}
public void setStage(Stage s)
{
if(currentStage != null)
{
currentStage.setActive(false);
}
foreach(Stage stage in stages)
{
stage.setActive(false);
}
s.setActive(true);
currentStage = s;
}
The debug line shows this:
And then it returns to 5 in the Update calls! Am I doing something really stupid and just don't see it?
Answer by Eudaimonium · Jun 01, 2016 at 03:09 PM
The "stages" list appears to be fine, it's the currentStage variable that's apparently broken.
My best guess is that it's never properly set to anything, that's why Debug.Log on the currentStage returns null. Consequently, getting IndexOf of the null object returns "-1" index if I'm not mistaken. Don't forget to set/assign/initialize your currentStage variable.
I am a bit stumped about the "MoveUp: 0" output, though... Is all the provided code within one same script? Could you perhaps post the entire script, and give it a brief commentary to see what gets called in what scenario?
using UnityEngine;
using System.Collections.Generic;
public class World : $$anonymous$$onoBehaviour {
[SerializeField]
private List<Stage> stages;
[SerializeField]
private Stage currentStage;
[SerializeField]
private int worldID;
private StageHandler stageHandler;
// Use this for initialization
void Start () {
Debug.Log("Start: " + stages.Count);
}
void Awake()
{
//The stageHandler reads a CSV file and makes stages based on that. It worked until I
//made world into a prefab.
stageHandler = GameObject.Find("StageHandler").GetComponent<StageHandler>();
//This is used by the stagehandler to choose the right stages.
worldID = 1;
//this calls the stageHandler and makes the stages. I do a similar thing for
//enemies and it works fine
loadStages();
//This makes the current stage the first stage on the list.
setStage(stages[0]);
Debug.Log("Awake: " + stages.Count);
}
void OnEnable()
{
Debug.Log("OnEnable: " + stages.Count);
}
void Update()
{
Debug.Log("Update: " + stages.Count);
}
public void loadStages()
{
stages = stageHandler.loadStages(worldID);
}
public void setStage(Stage s)
{
if(currentStage != null)
{
currentStage.setActive(false);
}
foreach(Stage stage in stages)
{
stage.setActive(false);
}
//At this point if I check for stages.Count there are still 5 stages.
s.setActive(true);
currentStage = s;
}
public void moveUpOneStage()
{
//This outputs 0. I don't know why and it makes no sense to me. Everywhere else is fine.
Debug.Log("$$anonymous$$oveUp: " + stages.Count);
int location = stages.IndexOf(currentStage);
Debug.Log(currentStage);
if(stages.Count > location)
{
setStage(stages[location + 1]);
}
}
public void moveDownOneStage()
{
int location = stages.IndexOf(currentStage);
if(location > 0)
{
currentStage.setActive(false);
currentStage = stages[location - 1];
currentStage.setActive(true);
}
}
}
This is the whole code for the class.
Wow... this shouldn't be happening :D
Everything looks fine to me, "setStage" is called in Awake and it sets the "currentStage" variable, so that should not be null.
Are there any other scripts or functions or events you execute whenever "moveDownOneStage" goes? What activates it, a button click event, or some other script calls it?
The script you posted looks fine to me, there has to be something else that's causing the error here.
It's a button that calls the move stage functions. Could it have something to do with that?
Answer by billybillyjim · Jun 01, 2016 at 03:59 PM
I figured it out! Thanks to Eudaimonium for helping me look in the right direction. The button was accessing the prefab instead of the instantiated prefab. I worked around this by writing some code for the button to find the instantiated prefab after it had been created with this:
world = GameObject.FindGameObjectWithTag("World").GetComponent();
You can just drag the instantiated prefab into the button's object field.
Or, if it's being instantiated dynamically (via code), then whenever you are instantiating it, you need to access the button and subscribe the newly instantiated object's function to the button click event.
Anyhow, glad it's working and that I was of some help :)
Your answer
Follow this Question
Related Questions
Destroy prefabs after they have been instantiated (C#) 1 Answer
Instantiated Object Has Wrong Rotation 0 Answers
Player trigger on platform with prefab 0 Answers
Mesh missing in prefab 0 Answers