Jump to content
  • Advertisement
ethancodes

C# GameManager destroyed error

Recommended Posts

I've got a state machine set up that I'm having an issue with. I have a Start scene, a Level_01 Scene, and a GameOver Scene. Each scene has a corresponding state. When the game starts, it sets the game to the Start scene. When I click the start button, it loads the Gameplay state. The game plays fine, but when you lose, the GameOver state does not load, the game continues to run, and I get one error that says the Game Manager has been destroyed and I am still trying to reference it. I have my managers set up on a Singleton pattern and I'm not sure how it's getting destroyed. This is my first time using both the state machine and the singleton, and I also have very little experience switching between scenes so I may be doing something simple wrong. The main thing I can tell you is that the currentState variable is coming back as null when I go to hit the GameOver state, and that the code is not even getting far enough to hit the OnDeactivate for the GamePlay state (probably because currentState is null). I'm really out of ideas on this one and haven't been able to find anything useful online. Hopefully someone can show me what I'm doing wrong. Thanks!

//Managers object code:

public class Managers : MonoBehaviour 
{
	public static Managers instance = null;

	private static GameManager _gameManager;
	public static GameManager Game 
	{
		get{ return _gameManager; }
	}

	private static UIManager _uiManager;
	public static UIManager UI 
	{
		get{ return _uiManager; }
	}

	private static LevelManager _sceneManager;
	public static LevelManager Level 
	{
		get{ return _sceneManager; }
	}

	private static BoardManager _boardManager;
	public static BoardManager Board 
	{
		get{ return _boardManager; }
	}

	private static PickUpManager _pickUpManager;
	public static PickUpManager PickUp 
	{
		get{ return _pickUpManager; }
	}

	private static SoundManager _soundManager;
	public static SoundManager Sound 
	{
		get { return _soundManager; }
	}


	void Awake ()
	{
		if (instance == null) {
			instance = this;
		} else if (instance != this) 
		{
			Destroy(gameObject);
		}

		DontDestroyOnLoad(gameObject);

		_gameManager = GetComponent<GameManager>();
		_uiManager = GetComponent<UIManager>();
		_sceneManager = GetComponent<LevelManager>();
		_boardManager = GetComponent<BoardManager>();
		_pickUpManager = GetComponent<PickUpManager>();
		_soundManager = GetComponent<SoundManager>();
	}
	
}

//GamePlayState code, other states are basically the same
 
public class GamePlayState : _StatesBase 
{
	public override void OnActivate ()
	{
		Debug.Log("GamePlay OnActivate");
		Managers.Level.LoadLevel("Level_01");
		Managers.Game.isGameActive = true;

	}

	public override void OnDeactivate ()
	{
		Debug.Log("GamePlay OnDeactivate");
		Managers.Game.isGameActive = false;
	}

	public override void OnUpdate ()
	{
		Debug.Log("GamePlay OnUpdate");
	}
}
          
 //GameManager code
          
public class GameManager : MonoBehaviour 
{
	public static MonoBehaviour monoBehaviour;
	public bool isGameActive;
	private int level = 50;
	private _StatesBase currentState;

	// Use this for initialization
	void Awake ()
	{	
		isGameActive = false;
		InitGame();
		monoBehaviour = this;
	}

	public _StatesBase State {
		get { return currentState;}
	}

	void InitGame ()
	{
		Managers.Board.SetupScene (level);
	}

	public void SetState (System.Type newStateType)
	{
		if (currentState != null) 
		{
			currentState.OnDeactivate ();
		}

		currentState = GetComponentInChildren (newStateType) as _StatesBase;
		if (currentState != null)
		{
			currentState.OnActivate();
		}
	}

	void Update ()
	{
		if (currentState != null) 
		{
			currentState.OnUpdate();
		}
	}

	void Start ()
	{
		SetState(typeof(MainMenuState));
	}
}
      
 //The load level method from the LevelManager
 public void LoadLevel (string name)
	{
		SceneManager.LoadSceneAsync(name);
		Brick.breakableCount = 0;
	}         
          

 

Edited by ethancodes

Share this post


Link to post
Share on other sites
Advertisement

Well, your Managers.Awake function looks fine - the DontDestroyOnLoad is what should be preventing your Managers from being auto-destroyed by scene loading.

I don't see a "GamePlay" manager anywhere in that code though... is that the actual error message you're getting?

Share this post


Link to post
Share on other sites

As the Game Manager class in a different script to the Manager class you need to be aware that unless you set specific execution order of scripts, unity can be a bit random as to what loads first. Setting execution order does not guarantee that the order will be respected though, but its worth trying.

From your code above i can see you're expecting the GameManager script to have already executed its "Awake" when you "Awake" the managers script... I'm guessing your error is occurring on the "GetComponent" for GameManager (seeing as that's your first component grab).

Can you supply the exact text out of the console showing the error? 

Share this post


Link to post
Share on other sites

I will get the exact error text when I get home tonight, and I can certainly try to set the order, but if this is the problem, shouldn't it be getting an error when the GetComponent fails? Not later when it tries to call a method on the GameManager? It's also not the first time the GameManger is being called on as it is already being used to load the Menu state when the game starts, and then called again to move from the Menu state to the Gameplay state. So I'm certainly using it a few times before I'm getting this error.

Share this post


Link to post
Share on other sites

GetComponent will return null if it can't find the component; it won't report any error until you try to use the null.  However, a destroyed component may give you a different error than one which just can't be found at all.

Regarding Stragen's comment about script-execution-order:  Another way to avoid issues with that is using Awake() to get all of your component references initialized, and then Start() for anything that needs to happen after all Awake() calls have been completed.

Share this post


Link to post
Share on other sites

So I put a Debug.Log in the Managers script in the Update function that checks Managers.Game == null. If it is, it puts a message in the Console. When the game starts up and pulls up the Menu scene, it works fine. However, it is returning null as soon as we switch scenes. So, important question that maybe someone had previously answered incorrectly. I was told I only need to put the DontDestroyOnLoad on the Managers script and since everything else is on that, they would also not be destroyed on load. Is it possible that I need to put DontDestroyOnLoad on each script?

 

EDIT: I tried this and it did not make a difference. Still trying to figure out the issue, I have attached the error I am getting.

error.PNG

Edited by ethancodes

Share this post


Link to post
Share on other sites

I thought DontDestroyOnLoad on a GameObject would keep all MonoBehaviours on that object alive, but I might be wrong.  Try calling it on the MonoBehaviours as well and see if that helps.

Share this post


Link to post
Share on other sites
Just now, Nypyren said:

I thought DontDestroyOnLoad on a GameObject would keep all MonoBehaviours on that object alive, but I might be wrong.  Try calling it on the MonoBehaviours as well and see if that helps.

Sorry I put in my edit on the previous post that I did try that and it did not work. Error was the exact same.

I tried it from both the individual scripts of the various managers, and also as gameObject.GetComponent<> on the Managers script. 

Share this post


Link to post
Share on other sites

Does it matter which scene the Managers game object is in? I have it in the Level_01 scene simply because that's where I'm always working in for most of the game so it makes it convenient to have in there so I don't have to switch between scenes for it. Then when the game starts it loads the Start scene (main menu). I don't believe it should be  a problem though since that game object should be persistent anyways right?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!