0
\$\begingroup\$

I've got a singleton set up with a overarching Managers class that has references to each of my other managers classes.

I also have a state machine set up that handles changing scenes between the Main Menu, the Gameplay, and the Game Over scene. These are also the corresponding states.

I'm using DontDestroyOnLoad on the Managers class so all that stuff should stay put between scenes.

The problem I'm running into however is that when it switches from the MainMenu to the Gameplay state, it apparently loses the reference to the GameManager object.

The error I get pops when I try to hit the GameManager for the second time when the game tries to change from Gameplay state to the Gameover state. It says it has been deleted, but if I put a debug.Log in the GameManager class's update function, it is still firing. I have tried to put a method in the Managers class that I could call to reassign it after the new level is loaded, but that doesn't seem to work.

I've pretty much tried everything I could think of, and asked on another site but nobody could figure it out there either. Hopefully somebody here can shed some light on what the problem is and how to fix it.

Below is all the code I think should be needed for this and also an image of the error I'm getting. Thanks everyone!

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>();
}

void Update ()
{
    if (Managers.Game == null) //this if statement is here simply to show me that Managers does not have a reference to this anymore
    {
        Debug.Log("This is null");
    }
}
}




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 ()
{
    Debug.Log("THIS IS A GAME MANAGER!!!"); //Just to check that it's still 
here. It is still showing even when Managers class reference is null.
    if (currentState != null) 
    {
        currentState.OnUpdate();
    }
}

void Start ()
{
    SetState(typeof(MainMenuState));
}
}


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");
}
}


public class LevelManager : MonoBehaviour 
{
public void LoadLevel (string name)
{
    SceneManager.LoadSceneAsync(name);
    Brick.breakableCount = 0;
}

public void QuitGame ()
{
    Application.Quit();
}

}

Error

\$\endgroup\$
0
\$\begingroup\$

Changing scenes destroys all game objects in that scene. Your GameManager is a MonoBehaviour and is therefore likely attached to a game object that is being destroyed.

\$\endgroup\$
  • \$\begingroup\$ Right but it was my understanding that using DontDestroyOnLoad would prevent that. It allows you to have persistent objects between scenes. \$\endgroup\$ – ethan codes Nov 3 '18 at 3:12
  • \$\begingroup\$ Besides that, it's already been established that the Game Manager has not been destroyed as it is still ticking off the debug.Log in the Update function even after Managers class reference is returning null. \$\endgroup\$ – ethan codes Nov 3 '18 at 3:14
  • \$\begingroup\$ Are you calling DontDestroyOnLoad on the GameManager's object? Looks like you're only calling it on the Manager's object and may have a (second, duplicate) version of GameManager in the new scene. \$\endgroup\$ – Draco18s Nov 3 '18 at 3:15
  • \$\begingroup\$ You should only need it on Managers. However this did already occur to me as a possibility and I did try to put DontDestroyOnLoad on the GameManager as well but it did not change the outcome. \$\endgroup\$ – ethan codes Nov 3 '18 at 3:17
  • \$\begingroup\$ Unity looks to be doing something weird then, I'm not sure. You might want to use a Singleton or Toolbox instead. \$\endgroup\$ – Draco18s Nov 3 '18 at 15:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.