Trying to write a simple pause script and cant figure out why it isnt working...

Hello, Im trying to write a simple pause script and cant figure out why it isnt working… All Im trying to do is pause or unpause the game when pressing the escape key but it wont pause. Ive found plenty of tutorials on this but they all do it differently so its making it hard for me to compare and see what Im doing wrong. Im sure its probably something obvious but I cant figure it out, anyone have any suggestions? Thanks

public class PauseScript : MonoBehaviour
{
    private bool pauseButton;
    public bool pauseBool;

    // Start is called before the first frame update
    void Start()
    {
#if UNITY_EDITOR || UNITY_STANDALONE
        pauseButton = Input.GetKey(KeyCode.Escape);
#endif

//#if UNITY_OTHER
        //pauseButton = Other.Input;
//#endif
    }

    // Update is called once per frame
    void Update()
    {
        if (pauseButton == true && pauseBool == false)
        {
            pauseBool = true;
            PauseGame();
        }
        else if (pauseBool == true && pauseButton == true)
        {
            pauseBool = false;
            ResumeGame();
        }
    }

    void PauseGame()
    {
        Time.timeScale = 0.0f;
    }

    void ResumeGame()
    {
        Time.timeScale = 1.0f;
    }
}

Edit: Oh, it’s even worse. You’re only checking the key status once when you start the script, and never checking again. Move line 10 down into the top of your Update() function.

When you call Input.GetKey(), it returns true for every Update where the user is pressing the key. An Update() is very quick while human fingers are pretty slow. That could be twenty updates in a row, where you would be toggling pause/resume state repeatedly. You want Input.GetKeyDown(), inside your Update function. This will return true for just ONE Update call at the moment they press the key, and will not return true again until they release the key and press it again.

There are other coding improvements to suggest but that’s the core of your issue here.

Line 10 above reads the escape key ONCE, then never again.

Line 10 does not set up a “live relationship” between pauseButton and the escape key being down.

Keep it simple, get rid of ALL those booleans, just use Time.timeScale and be done with it, like this:

Full script:

using UnityEngine;

// @kurtdekker
// Ultra-simple clean stateless in-game pause/unpause mechanism.
// TODO:
//    - put one of these script instances in your running game scene
//    - be sure to set Time.timeScale = 1 when your game starts

public class InGamePause : MonoBehaviour
{
    // anywhere in your game can observe this:
    public static bool IsPaused
    {
        get
        {
            return Time.timeScale == 0;
        }
    }

    void Update ()
    {
        bool pauseUnpauseCommanded = false;

        pauseUnpauseCommanded |= Input.GetKeyDown( KeyCode.Escape);

        //TODO : add any other "input sources" here, have them set the bool pauseUnpauseCommanded

        if (pauseUnpauseCommanded)
        {
            // flip Time.timeScale, which will be our ONLY state
            if (Time.timeScale == 0)
            {
                Time.timeScale = 1;
            }
            else
            {
                Time.timeScale = 0;
            }
        }
    }
}

Oh whoops, yeah I forgot that should be in Update, not Start. Thank you!

Sorry, didn’t see your reply when I posted mine. Yeah, I figured the way I was trying to use booleans was incorrect as well, that was my next step lol. But that definitely helps clarify a bit more, thanks!

Sorry, I’m a little confused about this…

I understand how I would access it elsewhere in my game, I’m just a little confused how it would work, since wouldn’t it always return timeScale == 0 regardless whether or not it’s paused?

It’s just a live getter to ask if your game is paused, and assumes timescale == 0 is paused, anything else is not paused.

It is static because Time.timeScale is static, and hence it can be used anywhere as:

if (InGamePause.IsPaused)
{
  Debug.Log( "Paused....");
}

Ohh alright, I’ve come across getters (and setters) a good bit so far but for some reason still been struggling to understand how they actually work, but that definitely helps to clarify what’s happening here, thanks!

Sorry, i know this is a stupid question but how do I access InGamePause.IsPaused from another script? I’ve done this a bunch of times before (even recently) now all of a sudden I’m struggling and just wasted 4 hours trying to figure it out -_- lol.

IsPaused is a static property, which means that this needs to be accessed via class instead of an instance.

public class MyClass : MonoBehaviour
{
    public static int staticField = 1;
    public int instanceField = 1;
}

public class OtherClass : MonoBehaviour
{
    private Start()
    {
        var referenceToInstance = GetComponent<MyClass>();
      
        referenceToInstance.instanceField = 2; // OK
        //referenceToInstance.staticField = 2; // WRONG
        MyClass.staticField = 2; // OK
    }
}

So, just type it in the way that you’ve typed here

Hmm… ok, I’m not sure if I’m having a hard time because it’s attached to a different game object or what.

Are you getting some kind of error? Because as static you do not need any kind of reference to be able to read the value, tbh this does not even need to be a component.

If i don’t add any reference it tells me

Here’s the error:

Assets\Scripts\CameraController.cs(47,13): error CS0176: Member 'ModifiedPauseScript.IsPaused' cannot be accessed with an instance reference; qualify it with a type name instead

As the error says “cannot be accessed with an instance reference;” you are probably trying to access this from the instance, can you post your CameraController script?

Well that’s what I figured but before adding a reference to an instance I was getting an error saying that InGamePause didn’t exist, so up until now it’s been a little circular trying to figure out the problem lol. That definitely helps helps narrow it down though. I’m about to leave for work but will post the code when I get home tonight

Ok, the only part of my script is

if (InGamePause.IsPaused == false)
{
    fov = Mathf.Clamp(fov, minFov, maxFov);
}

Which doesnt feel right because there’s no reference since its attached to a different gameObject (but if I try to add one then obviously thats also wrong)…

It’s just a static method. You may simply delete it if it bugs you so much. You don’t need it.

I was only offering it as a nice semantically-searchable way to avoid saying all over your code:

if (Time.timeScale == 0)
{
  Debug.Log( "I am paused");
}
else
{
  Debug.Log( "I am running");
}

Because if you hand this code to a non-unity person they are “what is timescale?” whereas IsPaused actually MEANS something.

It doesn’t really bug me, I’ve just somehow managed to never use static methods/variables up until now lol, I knew of them and i know they’re commonly used, just didn’t know actually using them was a little different… but I mean I’ve got to learn it eventually so I’ve been trying, plus I figured it just made sense to use since it was a cleaner solution than what I had (although mine worked it was messy) but I’ll just try something else then, thanks!

Ahh ok, I figured it out- it seems I just confused myself, because at first I was trying to reference my variable so that was causing issues (before Nefisto told me static variables/functions worked differently) then when I tried to correct it I forgot I named my class something different than InGamePause (since it wasn’t the name of Kurt’s script), for some reason I was thinking it was a method (or variable), not the class.

Got a few wires crossed, sorry. Also just picked it up again last week after putting it down for a couple months due to starting school and a new job (coupled with the fact that I can feel my mental capacity getting worse as I get older lol) just takes having to relearn a bit unfortunately. But I appreciate the help for sure, thanks!