Home > Software engineering >  Disable input and score count in pause menu?
Disable input and score count in pause menu?

Time:12-08

I need some sort of an if statement, which allows me to disable any input and incrementing score while I'm in the pause menu. The problem is that I don't really understand this kind of pausing code, I'm "used to" the regular boolean one. So, I show all the code.

First script:

public enum GameState
{
    Gameplay,
    Paused
}

Second script:

public class GameStateManager
{
    private static GameStateManager _instance;

    public static GameStateManager Instance
    {
        get
        {
            if (_instance == null)
                _instance = new GameStateManager();

            return _instance;
        }
    }

    public GameState CurrentGameState { get; private set; }

    public delegate void GameStateChangeHandler(GameState newGameState);
    public event GameStateChangeHandler OnGameStateChanged;

    private GameStateManager()
    {

    }

    public void SetState (GameState newGameState)
    {
        if (newGameState == CurrentGameState)
            return;

        CurrentGameState = newGameState;
        OnGameStateChanged?.Invoke(newGameState);
    }
}

Third script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PauseController : MonoBehaviour
{
    public void PauseGame()
    {
        GameState currentGameState = GameStateManager.Instance.CurrentGameState;
        GameState newGameState = currentGameState == GameState.Gameplay
            ? GameState.Paused
            : GameState.Gameplay;

        GameStateManager.Instance.SetState(newGameState);
    }
}

And as last, here is what I've done in my character movement script:

void Start()
    {
        GameStateManager.Instance.OnGameStateChanged  = 
        OnGameStateChanged;
    }

private void OnDestroy()
    {
        GameStateManager.Instance.OnGameStateChanged -= OnGameStateChanged;
    }

private void OnGameStateChanged (GameState newGameState)
    {
        enabled = newGameState == GameState.Gameplay;
    }

This is all the code. Where and how am I supposed to write the input and score increment "blockings"? I am so sorry for this being so long and I am grateful if you read all this! :)

CodePudding user response:

Approach 1. Where you have your score/input logic, you can check, if the state is Gameplay, and if not - just return. Like this:

if (currentGameState == GameState.Gameplay) 
{
     CheckInput();
     UpdateScore();
}
else
{
     return;
}

Another approach (better) is to have score update and input logic incorporated into current GameState. But you should rework your code:

You need the base GameState class:

public abstract class GameStateBase
{
     public abstract void UpdateScore();
     public abstract Vector2 GetInput();
}

Then you need 2 actual states, inherited from it:

public class GameStateGameplay : GameStateBase
{
     public override void UpdateScore()
     {
          //---- DO SOME SCORE LOGIC HERE
     }
     public override  Vector2 GetInput()
     {
          // for example, your input is mouse position:
          return Input.mousePosition;
     }
}

public class GameStatePause : GameStateBase
{
     public override void UpdateScore()
     {
          //---- DO NOTHING HERE, BECAUSE ITS PAUSE
     }
     public override  Vector2 GetInput()
     {
          //---- RETURN ZERO HERE, BECAUSE ITS PAUSE
          return Vector2.zero;
     }
}

Then, you need your state manager, simplified:

public class StateMachine
{
     public GameStateBase CurrentState;

     public void SetGameplay()
     {
          CurrentState = new GameStateGameplay();
     }

     public void SetPause()
     {
          CurrentState = new GameStatePause();
     }
}

Finally, where you doing your actual game logic, you can get current state - whatever it is, pause or gameplay - and let it handle your things:

private StateMachine _myStateMachine; // you can get it as a singleton instance, or somewhat else...

private void Update()
{
     _myStateMachine.CurrentState.UpdateInput();
    
     // assume, this is some PlayerObject:
     transform.position  = _myStateMachine.CurrentState.GetInput(); // Gameplay will return you actual input, and your object will move. Pause returns always zero, and object wouldn't move.
}

WHy it's better? Because this way you can implement as many states as you want. You can not create a new state everytime, but create it once, store references, and then just assign one to _current. You can make states as MonoBehaviours, and state machine too. It's highly recommended to learn about state machines, because it's used widely in game development.

CodePudding user response:

After hours of reading about state machines, I don't feel like I got any more into the topic. I understand now why is it optimal and for what its suggested use is. But I totally don't get the use of it in code. Sorry for the slow tempo, but can you show me how exactly do I have to implement this statement:

if (currentGameState == GameState.Gameplay) 
{
     CheckInput();
     UpdateScore();
}
else
{
     return;
}

Into my actual (for example) movement code?

void CheckInput()
{
    //if first input then ignore
    if (firstInput)
    {
        firstInput = false;
        return;
    }
    //here is where I want to implement, so if the game is paused, ChangeDirection will not play
    if (Input.GetMouseButtonDown(0))
    {
        ChangeDirection();
    }
}

Sorry again for having these basic questions, but I am not an expert (I bet you didn't realize it yet :D) and this is also so much different from a simple boolean.

  • Related