Pause menu only activates every other time a scene is loaded,Pause menu only works every other time a scene is loaded

Hello,

I’m having an issue where my pause menu only activates every other time my gameplay scene is loaded.
When starting the game from either the gameplay scene (build index: 1) or the main menu (build index: 0) the pause menu will function as expected (time freezes, HUD is disabled, pause menu UI enabled, controller line interactors enabled). However if the scene is reloaded (via going back to the main menu and back or upon player death), these attributes won’t trigger until the scene is reloaded once more. This continues to go back and forth forever. I can also trigger the pause menu on and off properly multiple times within the same scene instance while it is working properly.

Getting more specific, in the instances where the pause menu doesn’t work, the Inspector shows the correct game object references. When the menu button on the controller is pressed, the Debug.Log information displays the behavior that is expected, but this is not reflected in the gameplay. Example: Debug.Log("Time Scale: " + Time.timeScale) will display “0” or “1” when it’s supposed to, but the time in-game will not freeze. Also Debug.Log("HUD UI " + hudCanvas.activeSelf) will display “false” when expected, but the Canvas will still be visible in-game. It feels as though every other time the scene is loaded, it obtains references to the wrong instances of the GameObjects (including Time).

Here is the code for the Pause Menu (using Unity 2021.2.11f1):

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.XR.Interaction.Toolkit;

public class PauseMenu : MonoBehaviour
{
    [SerializeField] GameObject pauseMenuUI;
    [SerializeField] GameObject rightHandController;
    [SerializeField] GameObject leftHandController;
    [SerializeField] GameObject hudCanvas;
    
    bool gamePaused = false;

    public void ToggleMenu() // Triggered from Player script by controller button
    {
        if (gamePaused)
        {
            Resume();
        }
        else
        {
            Pause();
        }
    }

    void Resume()
    {
        hudCanvas.SetActive(true);
        pauseMenuUI.SetActive(false);
        Time.timeScale = 1f;
        gamePaused = false;
        SetControllerProperties(false);
    }

    void Pause()
    {
        hudCanvas.SetActive(false);
        pauseMenuUI.SetActive(true);
        Time.timeScale = 0f;
        gamePaused = true;
        SetControllerProperties(true);
    }

    void SetControllerProperties(bool isEnabled)
    {
        rightHandController.GetComponent<LineRenderer>().enabled = isEnabled;
        rightHandController.GetComponent<XRInteractorLineVisual>().enabled = isEnabled;
        leftHandController.GetComponent<LineRenderer>().enabled = isEnabled;
        leftHandController.GetComponent<XRInteractorLineVisual>().enabled = isEnabled;
        Debug.Log("HUD UI " + hudCanvas.activeSelf);
        Debug.Log("Enabled: " + isEnabled);
        Debug.Log("Time Scale: " + Time.timeScale);
    }

    public bool GetGamePaused()
    {
        return gamePaused;
    }

    public void MainMenu() // Triggered by UI Button Press
    {
        Time.timeScale = 1f;
        SceneManager.LoadScene(0);
    }
}

Why don’t you do Resume() before LoadScene(0)?

public void MainMenu() // Triggered by UI Button Press
{
    Resume();
    SceneManager.LoadScene(0);
}

If it still doesn’t work maybe there exist multiple PauseMenu objects, how are you loading the scenes except for MainMenu()? Do you use DontDestroyOnLoad() on any gameObjects?

@rh_galaxy using Resume() instead of Time.timeScale = 1is still rendering the same issue. as for using DontDestroyOnLoad(), I have a GameData object that is carrying a current score and high score. It’s only external interactions are when the player calls its AddToScore(int value) function and when it calls an “UpdateScore()” function from another object that references the score text within the HUD Canvas.

I found my issue was with my Player script rather than my Pause Menu. Since the XR Interaction Toolkit requires the new Input System, I needed to unsubscribe from the pause menu action when the script was destroyed. This is something that not all Input System tutorials go over. I have provided the following code for example. And thanks @rh_galaxy for taking the time to help out.

public class Player : MonoBehaviour
{
	[SerializeField] InputActionReference pauseAction;
	
	void Start()
	{
		pauseAction.action.performed += PauseGame;
	}
	
	//MUST INCLUDE
	void OnDestroy()
	{
		pauseAction.action.performed -= PauseGame;
	}
}