Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Need Advise

Discussion in 'Scripting' started by Genovine, May 4, 2022.

  1. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    I've been trying to get the UI to work and I'm about to start bashing my head against the wall. I've done dozens of tutorials and something always seems to break. How am I supposed to make a game when my attempts to transition from one Menu to another Menu or to Player controller seems to turn to dust?

    Any good tutorials that aren't outdated that are good at explaining foolproof transitions between menus and controllers. That means switching from player controller to the menu and opens the menu and can close the menu. Basically changing what state the player has control over.

    There seem to me good tutorials on movement, but every time I try and find something for menus with controllers, something seems to end up broken. Any good recommendations that aren't super confusing?

    I'm currently trying to use the UI so not sure what's wrong here. I set up and canvas and the joystick, but for some reason it doesn't work. Having more than one panel a problem or something? I'm trying to make Joystick specific, not interested in Mouse and Keyboard.

    I basically want to make a Start Menu, that allows me to start a new game. Then when the new level is loaded my character controller turns on. Then the player can open an inventory and scroll through the pages and then go back to he player controller. It's pretty silly, that something so basic to game design is hard to find..

    Honestly, the closest thing I got to a working controller, was just making static classes. But the UI seems to work with game objects and I cant seem to get it to work properly, it just seems to break when making a second menu.
     
    Last edited: May 4, 2022
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    You don't need to transition between menu inputs and player inputs? Both should be able exist in a scene at the same time and care little about one another. Or at the very least, opening up a menu should/could flick a switch to turn of the polling of player inputs, and flick it back on when it's closed.

    This can be as simple as a scriptable object or static class with a boolean value. The player controller checks if its true, and UI menus can flip it when they open/close.
     
    Brathnann likes this.
  3. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    Found the "First Selected" section and that seemed to do something. The second menu breaks still and nothing is selected. Are there ways to hardcode all this stuff, I would rather uses static classes and subscribe and unsubscribe to the new input system.
     
  4. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    Just got back from work, maybe I'll dive into UI Builder instead and try and make them in that. Can those styles sheets also be used for changing the menu design in an options menu? Where are the references on how to animate and setup controls for these things?
     
  5. Deleted User

    Deleted User

    Guest

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.SceneManagement;
    4. using UnityEngine.UI;
    5.  
    6. public class MainMenuManager : MonoBehaviour
    7. {
    8.     [SerializeField] private Button newGameButton;
    9.  
    10.     private void Start()
    11.     {
    12.         newGameButton.onClick.AddListener(StartNewGame);
    13.     }
    14.  
    15.     private void StartNewGame()
    16.     {
    17.         AsyncOperation loadScene = SceneManager.LoadSceneAsync("SceneName");
    18.  
    19.         while (!loadScene.isDone)
    20.         {
    21.             yield return null;
    22.         }
    23.     }
    24.  
    25. }
    26.  

    Not sure why you need to turn it on... should be on by default, right? Unless they load the new level and you're planning on showing a menu?

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class GameMenuManager : MonoBehaviour
    6. {
    7.  
    8.    [SerializeField] private Player player;
    9.  
    10.     [SerializeField] private GameObject inventoryMenu;
    11.  
    12.     [SerializeField] private Button closeInventoryMenuButton;
    13.  
    14.     private void Start()
    15.     {
    16.         closeInventoryMenuButton.onClick.AddListener(CloseInventoryMenu);
    17.     }
    18.  
    19.     private void Update()
    20.     {
    21.         // Never used joystick controls myself so not sure if this is correct.
    22.         if (Input.GetKey("joystick button 0")
    23.         {
    24.             player.playerControlActive = false;
    25.             inventoryMenu.SetActive(true);
    26.         }
    27.     }
    28.  
    29.     private void CloseInventoryMenu()
    30.     {
    31.         inventoryMenu.SetActive(false);
    32.         player.playerControlActive = true;
    33.     }
    34.  
    35. }
    36.  
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class Player : MonoBehaviour
    6. {
    7.  
    8.     public bool playerControlActive;
    9.  
    10.     private void Start()
    11.     {
    12.         playerControlActive = true;
    13.     }
    14.  
    15.     private void Update()
    16.     {
    17.         if (playerControlActive)
    18.         {
    19.             // only perform movement if player control is active.
    20.         }
    21.     }
    22.  
    23.  
    24. }
    25.  
     
  6. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    Thanks. There's definitely some good references that would help.

    One of my problems with tutorials online, would be that they show you how to do something, but then trying to implement them into the same project gets frustrating. That listener that you showed would be very similar to the new input system. The new input system is actually pretty good when you figure it out.

    When you want to use a Joystick, you can do something like this :

    Code (CSharp):
    1. using UnityEngine.InputSystem;
    2.  
    3. public static class GameStateTest
    4. {
    5.     // Have somewhere to reference the created input actions script.
    6.     // This can be in an entirely difference place from here.
    7.     private static PlayerActionInput PlayerInput = new PlayerActionInput();
    8.  
    9.     // Having references to the button selected with enums.
    10.     private static MenuIndex CurrentIndex = MenuIndex.Items;
    11.     private enum MenuIndex
    12.     {
    13.         Items,
    14.         Ability,
    15.         Options
    16.     }
    17.  
    18.     // Calling this method "activates" the functions with the gamepad.
    19.     public static void Enable()
    20.     {
    21.         PlayerInput.Gamepad.Movement.performed += ChangeTarget;
    22.         PlayerInput.Gamepad.ButtonSouth.performed += PressSouthButton;
    23.         PlayerInput.Gamepad.ButtonEast.performed += PressEastButton;
    24.  
    25.         PlayerInput.Enable();
    26.     }
    27.  
    28.     // Calling this method "deactivates" the functions with the gamepad.
    29.     public static void Disable()
    30.     {
    31.         PlayerInput.Disable();
    32.  
    33.         PlayerInput.Gamepad.Movement.performed -= ChangeTarget;
    34.         PlayerInput.Gamepad.ButtonSouth.performed -= PressSouthButton;
    35.         PlayerInput.Gamepad.ButtonEast.performed -= PressEastButton;
    36.     }
    37.  
    38.     // Use the gamepad to change the button selected.
    39.     private static void ChangeTarget(InputAction.CallbackContext Context)
    40.     {
    41.          // Method to Change CurrentIndex
    42.     }
    43.  
    44.     // Use the gamepad to activate that buttons methods.
    45.     private static void PressSouthButton(InputAction.CallbackContext Context)
    46.     {
    47.         // Select Button
    48.         switch (CurrentIndex)
    49.         {
    50.             case MenuIndex.Items:
    51.                 // Open Items Menu
    52.                 break;
    53.  
    54.             case MenuIndex.Ability:
    55.                 // Open Ability Menu
    56.                 break;
    57.  
    58.             case MenuIndex.Options:
    59.                 // Open Options Menu
    60.                 break;
    61.         }
    62.     }
    63.  
    64.     // Disable "this" controller, then Enable the "Player" Controller.
    65.     private static void PressEastButton(InputAction.CallbackContext Context)
    66.     {
    67.         // Back Button
    68.         Disable();
    69.         // Good place to put Animations between transitions.
    70.         PlayerAction.Enable();
    71.     }
    72. }
    You can basically make things easier with that Listener and the new Input system.

    I think the main problem with the Canvas UI is that there are multiple buttons throughout multiple panels and I think that screws up the "Event System" buttons. The first menu is completely fine, but when you open a new menu the buttons are all messed up.

    With the new Input system you can actually be very specific about what input you take. You can even just make the up and down buttons subscribed to their own methods. That way you can use enums to basically switch buttons based on the CurrentIndex. It's basically the same as trying to use the explicit navigation option in the inspector window.
    Code (CSharp):
    1.     public static void Enable()
    2.     {
    3.         PlayerInput.Gamepad.UpButton.performed += PressUpButton;
    4.         PlayerInput.Gamepad.DownButton.performed += PressDownButton;
    5.  
    6.         PlayerInput.Enable();
    7.     }
    8.  
    9.     public static void Disable()
    10.     {
    11.         PlayerInput.Disable();
    12.  
    13.         PlayerInput.Gamepad.UpButton.performed -= PressUpButton;
    14.         PlayerInput.Gamepad.DownButton.performed -= PressDownButton;
    15.     }
    16.  
    17.     private static void PressUpButton(InputAction.CallbackContext Context)
    18.     {
    19.         // Up Button
    20.         switch (CurrentIndex)
    21.         {
    22.             case MenuIndex.Items:
    23.                 CurrentIndex = MenuIndex.Options;
    24.                 break;
    25.  
    26.             case MenuIndex.Ability:
    27.                 CurrentIndex = MenuIndex.Items;
    28.                 break;
    29.  
    30.             case MenuIndex.Options:
    31.                 CurrentIndex = MenuIndex.Ability;
    32.                 break;
    33.         }
    34.     }
    35.  
    36.     private static void PressDownButton(InputAction.CallbackContext Context)
    37.     {
    38.         // Down Button
    39.         switch (CurrentIndex)
    40.         {
    41.             case MenuIndex.Items:
    42.                 CurrentIndex = MenuIndex.Ability;
    43.                 break;
    44.  
    45.             case MenuIndex.Ability:
    46.                 CurrentIndex = MenuIndex.Options;
    47.                 break;
    48.  
    49.             case MenuIndex.Options:
    50.                 CurrentIndex = MenuIndex.Items;
    51.                 break;
    52.         }
    53.     }
     
    Last edited: May 5, 2022
    Deleted User likes this.
  7. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    Found a video that helps for anyone with similar problems.
     
  8. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    Why is finding knowledge on gamepad development so difficult? You can create everything super fast when you develop with Mouse, but gamepad instantly becomes extremely difficult to find information for.

    We are talking about the things that are basically in 99% of console video games. Almost every single console uses the gamepad to navigate multiple menus in games. Anyone know of resources where they explain things for the normal person, who isn't considered a computer whisperer?

    I can make an entire game quickly with the input system and debug logs, but when time to integrate this UI system, things become too convoluted and documentation is hard to find. It's like I'm fighting with the UI system when wanting to make a game with a gamepad.

    Also. What do the UI buttons actually do? Example : The Event System has a Cancel button. I can assign that to the Gamepad B button. But what does this even do, when you cant even find where or how to assign what the Cancel button does?
     
    Last edited: May 7, 2022
  9. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    Probably because there isn't/shouldn't be a difference between coding for inputs from a keyboard or a controller. Both input hardware can fire off the same events that the UI can respond to. If I remember, by default, the Event System should be set up to allow straight-forward navigation.

    To answer your comments about the 'cancel button', I believe you can either use the ICancelHandler interface, or an Event Trigger. As per the links this is all pretty much covered in the documentation, which should be your first resource for learning, not youtube tutorials.
     
  10. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    The event system navigation breaks when dealing with multiple menus. You have to hard-code all the "entry button" selection events and all the "exit button" selection events. The only time it works is when dealing with one menu and it's the first time entering the scene. When using a "mouse" that option becomes redundant.

    Example : Enter Main Menu ( Hard-Code First Button ), enter items menu ( Hard-Code First Button ), exit item menu ( Hard-Code Last Button ) which is basically how most gamepad menus work.


    The unity documentation is hard to navigate and sometimes way too vague and confusing to even be helpful. You're talking to someone who doesn't speak computer, and see the most vague description of something.

    What does ICancelHandler even do?

    Page One : Criteria for this event is implementation dependent. For example see StandAloneInputModule.
    Page Two : Input manager name for the 'cancel' button. "public string cancelButton { get; set; }"

    How does that seem remotely helpful to the average human?

    I can just "PlayerInput.Gamepad.EastButton.performed -= CancelButton;"
     
    Last edited: May 7, 2022
  11. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    Event triggers swallow up inputs, which is noted in the documentation page I linked. Really only one for each input should be present.

    It literally says:
     
  12. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    What does "swallow up inputs" even mean?

    You have to manually type :
    EventSystem.current.SetSelectedGameObject(null);
    EventSystem.current.SetSelectedGameObject(NewButton);

    Every time you change between one menu to another menu. Otherwise it breaks, as the current selected button would still be in the first menu, while you're in the second menu. And following conventional intuitive menu design, the back button should always come back to the last selected button when you exit. So when you exit the options menu, that button should be the first thing selected when exiting the options menu.

    If you have ever played a video game on console you would see this. Because that's how gamepad menus have worked since the dawn of time. It's also how the player isn't confused when they press the back/cancel button, when exiting a hierarchical menu.

    And what does this mean to the average human?
     
    Last edited: May 7, 2022
  13. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    It means if there's multiple event triggers expecting the same input, the first one that receives the trigger will prevent others from receiving it.

    It 'swallows up' the input, if you will, so nothing else gets it.

    I get the feeling you're expecting Unity to do everything for you. It doesn't. If you want this sort functionality, you need to implement it yourself.

    That isn't to say everything has to be hard coded. It's very easy to make your own general purpose UI system manager to automates a lot of this functionality in such a way that it can be used across most if not all of your UI menus. I've done so, and I'm sure many other users here have as well.

    You should spend some time learning some of the more common programming terminology that you'll encounter. It's an interface. You implement interfaces as opposed to inheriting from classes.

    Example:
    Code (CSharp):
    1. public class SomeUIComponent : Monobehaviour, ICancelHandler
    2. {
    3.     public void OnCancel(BaseEventData eventData)
    4.     {
    5.         //do stuff here
    6.     }
    7. }
     
    Deleted User likes this.
  14. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    You're literally talking about functionality inherent to most console video games. You would think an engine designed for game development, would at least be intuitive for console development.

    At least the new input system is good and makes the UI Event System pretty redundant, when you have to assign Select, Cancel, Left Trigger, Right Trigger and Start buttons. While the UI system only gives you one button with OnFire capability.

    At the moment, I only use them for "Wait For Seconds" between things. Not sure what other things that are game related they would be used for really

    Most things I'll be using have to do with the Gamepad, Audio, Animations and basic data management. I'm going for the classic JRPG feel, probably going to use NavMesh for even the players movement restrictions. While Jump is only at specific Trigger locations, just like OpenChests and OpenDoors. It's not going to be too complex, but graphics, animations, music and setting up the story and levels will take loads of time.
     
    Last edited: May 7, 2022
  15. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    And yet it is. You can specify multiple input devices for the same input action. Beyond that, it's up to you how those inputs behave. If you don't care to develop it yourself, I'm sure there's stuff on the asset store that can make this easier for you.

    Um, what? WaitForSeconds isn't an interface, it's a class. Interfaces are a C# thing. If you're going to be coding you need to learn core C# concepts as much as you learn Unity. It will take you a long way.
     
  16. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    What made the UI Buttons appealing was the automatic changing of button icons when selected and activated. Not sure I'll need to go to the asset store to learn how to animate things. Well, I sure hope not...

    See, my terminology is mixed up. I apparently have already use Interfaces, but never put "I" at the start. Basically, used for my State Machine with the Enter, Exit, Execute methods.

    The "Wait For Seconds" was actually something else, an IEnumerator.

    Code (CSharp):
    1. public class Coroutine : MonoBehaviour
    2. {
    3.  
    4.     // Call this to delay time between methods
    5.  
    6.     static public Coroutine Instance;
    7.     void Awake()
    8.     {
    9.         Instance = this;
    10.     }
    11.  
    12.     public static void DelayAction(float WaitTime)
    13.     {
    14.         Instance.StartCoroutine("DelayCoroutine", WaitTime);
    15.     }
    16.  
    17.     private static IEnumerator DelayCoroutine(float WaitTime)
    18.     {
    19.         while (true)
    20.         {
    21.             yield return new WaitForSeconds(WaitTime);
    22.         }
    23.     }
    24. }
     
  17. Genovine

    Genovine

    Joined:
    May 25, 2014
    Posts:
    21
    And the tutorials repeat the same things, almost feels like Click Bait.

    But I have to admit, some are pretty good and I've learned a few things.