Search code examples
c#unity-game-enginescene

Unity, reload scene completely


I have two scenes: Menu and Game where the maze is randomly generated every launch.

After the Player dies in the maze I load the scene Menu where the Player can press button Start which should generate a new maze but instead it just loads the old scene with maze where Player died earlier.

I want to generate the new maze every time after pressing Start button.
Also, when I play the scene with maze separately everything works correctly For scene loading I use:

SceneManager.LoadScene(sceneIndex);

with indexes defined in Build settings.

If any additional code is needed just ask me and I will add it.

UPDATE
I have a class MazeGenerator where I have delegate and event:

public delegate void MazeReadyAction();
public static event MazeReadyAction OnMazeReady;

Event triggers when the maze is generated and is used in MazeDirecives class to set the Enemies and Coins when the maze is ready.
So that I MazeDirectives have lines:

void Awake()
{
    MazeGenerator.OnMazeReady += StartDirectives;    
}

void StartDirectives()
{
   for (int i = 0; i < mazeCoinPositions.Count; i++)
    {
        MazeCoin mazeCoin = Instantiate(mazeCoinPrefab, mazeCoinPositions[i], 
            Quaternion.identity) as MazeCoin;
            mazeCoin.transform.SetParent(transform);
    }
}

Error:
MissingReferenceException: The object of type 'MazeDirectives' has been destroyed but you are still trying to access it pups up on:

mazeCoin.transform.SetParent(transform);

Any suggestions?


Solution

  • Since

    public static event MazeReadyAction OnMazeReady;
    

    is static it keeps being there also if there woud be an instance of that class being destroyed.

    So that after

    MazeGenerator.OnMazeReady += StartDirectives;
    

    that listener keeps being called though the MazeDirectives object you registered as listener is getting destroyed because of SceneManager.Load. So the next time when OnMazeReady is called you have actually two listeners registered: The one from the first scene which now is destroyed, and the one from the "new" scene.

    You should either remove the old listener

    private void OnDestroy()
    {
        MazeGenerator.OnMazeReady -= StartDirectives;
    }
    

    or not even "stack" them but only asign exactly one listener

    private void Awake()
    {
        MazeGenerator.OnMazeReady = StartDirectives;
    }
    

    this does ofcourse only apply if there is no other listener in your scene.

    Anyway you should reset it just to be sure

    private void OnDestroy()
    {
        MazeGenerator.OnMazeReady = null;
    }
    

    General Note: It is always save to call

    MazeGenerator.OnMazeReady -= StartDirectives;
    

    even if the listener wasn't added before. So doing

    private void Awake()
    {
        MazeGenerator.OnMazeReady -= StartDirectives;
        MazeGenerator.OnMazeReady += StartDirectives;
    }
    

    also makes sure that the listener can allways be added only exactly once.