Search Unity

How do you organize your menu state?

Discussion in 'Scripting' started by Alan47, Apr 1, 2020.

  1. Alan47

    Alan47

    Joined:
    Mar 5, 2011
    Posts:
    163
    Hello everyone,

    I recently developed a main menu (ESC-menu) for a first-person game. I soon realized that, while the code is not that difficult, it will be a burden in the long run unless I put it in the right place.

    Let's assume that the game will have two menus, which act as "modal windows" (i.e. the player can't do anything except interact with them while they are open; only one of them can be open at any point in time):
    • A pause menu (ESC menu)
    • An inventory screen

    There are several solutions I've come across to establish the "modal window" behaviour:
    1. Set "Time.timeScale" to zero to pause the game and hope that player controls will have no time-independent side effects
    2. Disable the player game object while the menu is open, re-enable on menu close
    3. Disable the script component that reads the player input while the menu is open, re-enable on menu close
    4. Have a global static boolean, something like "IS_MAIN_MENU_OPEN" and check that everywhere (e.g. don't allow the player to move if the inventory is open, don't allow him to open any other menus etc.)
    5. Disable the menu input actions in the action map (new input system)
    6. Check the "isActive" state of the respective UI GameObjects (retained mode UI only of course)
    Option #1 will work only for very simple games where there is only one menu. As soon as you have multiple menu screens (e.g. the player inventory and the pause menu), simply setting the timescale to zero will not suffice, as the player will be able e.g. to open the inventory while the main menu is up.

    Option #2 seems very radical, as it makes the player disappear from the scene entirely. Not really an option IMHO.

    Option #3 seems a bit hacky to me. In particular, the menu needs to have a reference to the player GameObject in order to perform the component disabling/enabling. The main menu doesn't really care about the player GO in the first place. Separation of concerns clearly says "no" to this solution.

    Option #4, while it would work, is not very elegant; a lot of game logic and input logic may depend on whether or not a menu is open. This check would be all over the place.

    Option #5 seems very elegant at first sight, but requires that ALL game objects share one common instance of the action map; otherwise one of them will have game controls disabled while the menu is up, and all others will not. As it seems to be best practice (according to various Unity tutorials) to create a new action map instance per MonoBehaviour, this solution seems unrealistic.

    Option #6 would work, but requires all objects to have a reference to the menu UI - leading to really bad separation of concerns.

    Maybe there are further options I didn't think about? Which solution(s) do you use in your projects?

    Thanks,

    Alan