2
\$\begingroup\$

So, I'm currently learning both about Unity for the first time as well as the 'new' 2D UI system, but I'm having a hard time figuring out how to make windows, modals/dialogs, main menus etc. which are not only functioning, but also modular, reusable and written following proper coding standards. Most how to's, blogs, Q&As or tutorials I find only cover the most basic parts of UI development (e.g. how to drag a button from the toolbar to the scene window in 2 hours).

So basically, I'd like to have a main menu which meets those (very common) requirements:

  • A button which 'starts' the game (e.g. by simply loading another scene)
  • A button which 'quits' the game, but also opens up a confirmation dialog before
  • A button which opens up an options dialog, which again is composed of multiple parts (audio, video...)
  • and finally, it should be possible to go back to the previous screen using a 'back key/button', for example Escape

What I started with is a canvas which I called GameMenu. This canvas has several nested canvases, such as

  • MainMenu
  • OptionsMenu
    • OptionsMenuAudioPart
    • OptionsMenuVideoPart
  • CancelMenuModal

Then I created a menu script which works as some sort of state machine:

public class MenuScript : MonoBehavior {

    private GameObject _currentStateObject;
    private GameObject _previousStateObject;

    public void SetState(GameObject newStateObject) {
        if(newStateObject == null || newStateObject)
            return;

        if(CurrentStateObject != null)
            CurrentStateObject.SetActive(false);
        _previousStateObject = _currentStateObject;
        CurrentStateObject = newStateObject;
        CurrentStateObject.SetActive(true);
    }
}

Every button has now an event trigger attached which calls the SetState(...) method on MenuScript.

However, I've got the following problems:

  • How do I pass multiple parameters to methods invoked by event triggers? As soon as I add another parameter to SetState(...), for example bool isModal = false to tell the method that it shouldn't disable the previous state, then it disappears from the event trigger action selection menu.
  • How to I register key press events within the event triggers? It's easy by script (Input.GetKey(...) etc.), but I didn't find one on the event type selection.
  • How do I make e.g. event triggers conditionally? So that certain events cannot be called when certain states are active?

I know I can solve all those problems within the script and make a fully functional main menu which does exactly what I want, but then...

  • I cannot use it for something else
  • I don't use the new Unity UI system, which makes me wonder what's the purpose of it
  • I got to reference all involed game objects (the canvases, buttons etc.) in script, which makes it not really 'extendable' anymore as this means for every changed requirement, I have to alter the script (e.g. a new state, menu, button etc)

The main goal in the end is a script which I can use for all kinds of UIs without writing the same logic over and over again just because it's another scene, game state etc.

\$\endgroup\$
  • 6
    \$\begingroup\$ This is kind of like a bunch of questions all glommed into one. Ask seperate narrowly-defined questions so we can give definitive answers to each. \$\endgroup\$ – Almo Mar 21 '16 at 22:21
  • \$\begingroup\$ @Almo Kind of. Yes, it's a 'bigger' task where I've got several individual problems with, but in the end I'm trying to implement a simple concept (re-usable main menu script using a state machine and kind-of code/UI components separation) that doesn't make sense when the problems are provided individually. For instance, I already figured out that I can pass e.g. scriptable objects as parameters for event trigger invocations and therefor I can make some sort of property bags (solution for problem 1)... \$\endgroup\$ – artganify Mar 21 '16 at 22:26
  • \$\begingroup\$ @Almo ...but this couples the scene graph to the script event more (general problem) and doesn't make much sense in the case of problem 2 (input) which is related to the 'Escape->go back' requirement. Posting all those things in individual questions would just be 3 times copy-paste the upper 75% of the post with a single sentence as the question. And that would generate just a lot of noise. \$\endgroup\$ – artganify Mar 21 '16 at 22:28
0
\$\begingroup\$

I have system like OMCV - Object Model Controller View. If this helps you. In Objects I have data objects (models) that are sent to Controller which decides to what view to assign the data. In your case you could have a Controller that has calls to Views and use it by calling methods from controller from Buttons.

But for this purpose I would have different Views that are Models and Controllers of itself.

For example, Confirmation Window - it has a method public void ApplyConfirmation(UnityAction buttonConfirmationAction, string text); - and when you click on exit button wich has some method applied to if from MenuManager or whatever which has a call to Confirmation Window.

ConfirmationWindow.Instance.ApplyConfirmation(delegate { this.ExitGame(this.SaveDataBeforeExit) }, "Do you really want to exit?");

Now confirmation window pops up. ApplyConfirmation in my case has an "Yes" button which is asigned any method to be called when it's pressed and a text that changes the text on pop up window.

If you are sure that you are going to have only 1 UI element of that behavior and you can reuse it - you can go ahead and make it a Singleton to be able to call it easily from any class like UIElementClassName.Instance.PublicMethodToCall();

Hope you got the idea from it.

\$\endgroup\$
-1
\$\begingroup\$

If you want a modular UI you can use and implement different fonts/texts, I'd write my own gui texture's fonts ect and have a OnGui holding all the options you want then simply either create functions regarding each option or have multiple scripts. Regarding 'noise' if it works it works, having a simple:

audioMenu = false; mainMenu = true;

Can simply revert u back to the main screen.

\$\endgroup\$
  • 1
    \$\begingroup\$ OnGUI is old and should no longer be used. Use the new UI \$\endgroup\$ – Draco18s May 22 '17 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.