- Home /
Getting Debug log errors when I load my scenes
I have a class that handles loading levels randomly as illustrated by this diagram:
This is the class I created:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
[ExecuteInEditMode]
public class ReferentManager : MonoBehaviour
{
FinalGUIWindow cs_finalWindow;
protected const int MAX = 2;
private List<int> scenes;
void Start()
{
cs_finalWindow = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<FinalGUIWindow>();
scenes = new List<int>(Enumerable.Range(1,MAX)); // This creates a list with values from 1 to 2
OnLevelWasLoaded(0);
DontDestroyOnLoad(gameObject);
}
void Update()
{
if (scenes.Count <= 0)
{
cs_finalWindow.showCompletedWindow();
}
}
void OnLevelWasLoaded(int index)
{
var defaultScene = GameObject.FindObjectOfType<FirstScene>();
if (defaultScene != null)
{
defaultScene.OnLoadNextLevel -= OnLoadNextLevelHandler;
defaultScene.OnLoadNextLevel += OnLoadNextLevelHandler;
}
var nextScene = GameObject.FindObjectOfType<SecondScene>();
if (nextScene != null)
{
nextScene.OnLoadNextLevel -= OnLoadNextLevelHandler;
nextScene.OnLoadNextLevel += OnLoadNextLevelHandler;
}
var lastScene = GameObject.FindObjectOfType<ThirdScene>();
if (lastScene != null)
{
lastScene.OnLoadNextLevel -= OnLoadNextLevelHandler;
lastScene.OnLoadNextLevel += OnLoadNextLevelHandler;
}
}
private void OnLoadNextLevelHandler()
{
int randomIndex = Random.Range(0, scenes.Count);
int level = scenes[randomIndex];
scenes.RemoveAt(randomIndex); // Removes the level from the list
Application.LoadLevel(level);
}
}
The class doses what it should be doing but once it gets to a certain point in the game it gives me the following issues:
->When I load the first random scene everything runs fine. ->When I load the second random scene it gives me this error:
Line 25: NullReferenceException: Object reference not set to an instance of an object ReferentManager.Update ()
->The strange thing is that I can run through this scene fine in spite of all the debug log errors is spamming. ->Then after I am done with that scene the debug window spams the next debug errors:
Line 52: ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[System.Int32].get_Item (Int32 index)
ReferentManager.OnLoadNextLevelHandler () (at Assets/Scripts/General Scripts/ReferentManager.cs:52)
Cube_SceneManager.displayScene () (at Assets/Scripts/GUI Scripts/Cube Scene/Cube_SceneManager.cs:58)
Cube_SceneManager.OnGUI () (at Assets/Scripts/GUI Scripts/Cube Scene/Cube_SceneManager.cs:35)
Can anyone help me understand why I am getting these errors? Thank you in advance and happy holidays!
Answer by Tomer-Barkan · Dec 24, 2013 at 04:16 PM
The Null Reference exception is probably because cs_finalWindow is null. You're setting it to reference an object in the current scene, but as soon as you switch scene, that object (the main camera) is destroyed, and you can no longer use it. I suggest you move the script FinalGUIWindow from the main camera object, to be in the same object as the reference manager, since this object is not destroyed when you switch scenes.
The ArgumentOutOfRangeException is caused because the list scenes
is empty. The OnLoadNextLevelHandler() is still called after you remove all the scenes from the list, so it causes this exception. The solution is to check whether it's empty:
private void OnLoadNextLevelHandler()
{
if (scenes.Count > 0) {
int randomIndex = Random.Range(0, scenes.Count);
int level = scenes[randomIndex];
scenes.RemoveAt(randomIndex); // Removes the level from the list
Application.LoadLevel(level);
}
}
Try to add a Debug.Log before removing a scene from the list, see why it happens when it shouldn't. Also make sure it starts out with the correct amount of scenes in it, so maybe print out how many scenes in the list before removing one.
Answer by tom_eberhard · Dec 24, 2013 at 05:35 PM
It's architected a bit strangely, and one of the problems is (probably) that you're removing scenes at randomIndex.
I would architect this a bit differently: Keep a sceneIndex variable, and randomize the scene list before going through the levels.
Also, I'm not sure what you're trying to do with these lines:
defaultScene.OnLoadNextLevel -= OnLoadNextLevelHandler; defaultScene.OnLoadNextLevel += OnLoadNextLevelHandler
Anyway, here's something to get you going in (hopefully) a better direction:
public class LevelManager : MonoBehaviour {
protected const int MAX = 12;
private int[] scenes;
private int sceneIndex;
// Use this for initialization
void Start () {
Debug.Log ("LevelManager: Hello");
scenes = new int[MAX];
FillList(scenes);
PrintList (scenes);
RandomizeList (scenes);
PrintList (scenes);
sceneIndex = 0;
OnLoadNextLevelHandler ();
Debug.Log ("LevelManager: Bye");
}
// Update is called once per frame
void Update () {
if (sceneIndex == MAX-1)
{
//cs_finalWindow.showCompletedWindow();
}
}
private void FillList(int[] list)
{
Debug.Log ("FillList: Hello");
for (int i=0; i<MAX; i++) {
list[i] = new int();
list[i] = i;
}
Debug.Log ("FillList: Bye");
}
/// <summary>
/// Randomizes the list, but keeps the first and last element in place (the First Scene and the Last Scene)
/// </summary>
/// <param name="list">List.</param>
private void RandomizeList(int[] list)
{
int temp;
int randomIndex;
Random.seed = 32192;
for (int i=1; i<list.Length-1; i++) {
randomIndex = (int)Mathf.Floor(Random.Range (1,list.Length-2));
// swap list[i] and list[randomIndex]
temp = list [i];
list [i] = list [randomIndex];
list [randomIndex] = temp;
}
}
private void PrintList(int[] list) {
Debug.Log ("Printing List");
string s = "";
for(int i=0; i<MAX;i++)
{
s = s + list[i].ToString("0") + ",";
}
Debug.Log ("list.Count = " + list.Length.ToString ());
Debug.Log (s);
}
private void OnLoadNextLevelHandler()
{
//Application.LoadLevel(sceneIndex);
sceneIndex++;
}
}
it's not really necessary, I had used it to debug the RandomizeList() function so that I would get the same random sequence each time. Remove it, and then you'll get a different sequence each time.