MissingReference After Application.LoadLevel. I dont use DontDestroyOnLoad

I have a main menu, and a game level. If the game is lost, the main menu should load (via application.LoadLevel("...") ) and if "start game" is selected the level loads (again) also via application.LoadLevel. Well everything works perfectly fine the first cycle. But if the game is lost the 2nd time, I get a MissingReference.

MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.

and here is the code where the error is caused

    private void endTheGame(){
    alive = false;
    Destroy(Player);
    mainCamera.animation.Play("CameraDeath");
}

In the inspector I can see that the "mainCamera" variable is filled with the maincamera gameobject so it cant be null actually. What I think is that the script is still trying to access the first instance of the camera and not the second which was created during the reload of the level. But I have no idea how this can happen. I also use the c# messenger to call the endTheGame() function. dont know if that makes any difference.

All I found on google was that people have this kind of problems when they use " DontDestroyOnLoad" but I am not using it anywhere in my scripts. And I got the same problems when I tried to start a coroutine instead of the animation, so I doubt that the Animation.play is a problem.

Just in case this is the complete script

using UnityEngine;

using System.Collections;

public class GameMaster : MonoBehaviour {

public GameObject baseCamera = null; 
public GameObject mainCamera = null; 
private GameObject Player;
private GameObject Base;
public  bool baseAlive = true;
public  bool alive = true;

void OnEnable() {
    // Remove listeners
    Messenger.AddListener("Player killed", endTheGame);
    Messenger.AddListener("Base killed", BaseDown);
}

void OnDisable() {
    // Remove listeners
    Messenger.RemoveListener("Player killed", endTheGame);
    Messenger.RemoveListener("Base killed", BaseDown);
}

// Use this for initialization
void Start () {
    Player = GameObject.Find("tps_player");
    Base = GameObject.Find("Base");
    baseCamera.camera.enabled = false;
    (baseCamera.GetComponent(typeof (AudioListener)) as AudioListener).enabled = false;
    Messenger.AddListener("Player killed", endTheGame); //messenger in enemy AI
    Messenger.AddListener("Base killed", BaseDown); //messenger in enemy AI
}

void Update(){
    if(alive == false){
        if(!mainCamera.animation.IsPlaying("CameraDeath")){
            backToMainMenu();
        }
    }
}

private void endTheGame(){
    alive = false;
    Destroy(Player);
    mainCamera.animation.Play("CameraDeath");
}

private void BaseDown(){
    baseAlive = false;
    Debug.Log("The Base is gone, no more upgrades for you");
    Destroy(Base);
}

private void backToMainMenu(){
    Application.LoadLevel("mainMenu");
}

}

3 Answers

3

Hi. I can't directly offer an answer yet at this point as I am currently facing the same problem. However on first glance I noticed that both of us are utilizing the Messenger class. One possibility that jumps out at me is that the Messenger class is referring to an older object from the previous game scene load.

You imply that the mainCamera is the culprit but never say that it's that specific line in that chunk of code that is pointed to, so perhaps the Messenger angle is another thing to check - that's the direction I'll be going when I look at my code.

Just tested the above idea... Turns out in my case it was indeed my use of the Messenger class that was the problem. All I had to do was ensure that each of my 'Messenger.AddListener("whatever", FunctionName);' in Awake() simply needed to be properly matched with a 'Messenger.RemoveListener("whatever", FunctionName);' in OnDestroy(). Simple oversight and simple fix :)

I had the same error with some objects I created inside Start() via GameObject.Find() and GetComponent() in a C# project.

Instead of Messenger.AddListener(), I was using Delegates & Events like Prime31’s plugins:

    void Start() {				
    ...				
		MyGameObject1 = GameObject.Find("HUD_Manager");		
		MyHUD = (HUDscript) MyGameObject1.GetComponent<HUDscript>();			
			
    	HUDScript.onContinue += onContinueStuffHandler;			
    ...
    }

Adding an OnDestroy, destroying obj created inside Start and unsubscribing from events fixed the problem:

	void OnDestroy() {
		
		FormsScript.onFormsFinish -= onFormsFinishHandler;			
		
		TimerScript.onTimeFinish -= onTimerFinishHandler;				
		HUDscript.onPause -= onPauseItHandler;				
		HUDscript.onUnPause -= onUnPauseItHandler;				
		HUDscript.onContinue -= onContinueStuffHandler;		
				
		Destroy( MyGameObject1 );
		Destroy( MyGameObject2 );
		Destroy( MyGameObject3 );
		Destroy( MyGameObject4 );						
		
		Destroy( MyGameSettings );
		Destroy( MyHUD );
		Destroy( MyTimer ); 		
	}

woohoo, this really helped me! tnx

Same problem for me, and same solution: I use a GameManager to which GameObject registers themselves. The problem was solved unregistering objects in OnDestroy method implementation.