Unity Menu System
Declarative menus, shared UI themes and predictable navigation, configured as assets instead of hand-wired GameObjects.
What the system is for
Most Unity projects start with a couple of buttons on a Canvas and grow into a tangled web of scenes, prefab variants and direct references. Pause menus, settings menus, level select screens and confirmation flows all end up with their own ad hoc wiring. The result is fragile UI code that is painful to localize, restyle or extend.
The Menu System in Serenity describes menus as data. Each menu is a definition asset with options, transitions and presentation rules. A single service consumes those definitions at runtime, drives the views and dispatches the right signals when the player selects something. You configure menus instead of stitching prefabs together.
The Unity problem
Unity menus tend to grow in three painful ways at the same time. Visually, each new screen copies a prefab and starts to drift from the rest of the UI. Behaviorally, button OnClick handlers reference scene objects, managers and singletons that may or may not exist when the scene loads. Structurally, the same code is duplicated between the main menu, the pause menu and any in-game overlays.
On top of that, menus are the surface where localization, theming, input, audio feedback and settings persistence all meet. If any of those systems is wired ad hoc, every menu becomes a small bug surface. Localized labels go out of sync, themes get baked into prefabs, gamepad navigation breaks on certain panels and confirmation dialogs reinvent themselves three times in the same project.
How Serenity approaches it
Serenity treats a menu as a configuration unit. A menu settings definition declares the options, the available views and the data each option needs. A menu service reads those definitions and exposes a small set of use cases such as selecting an option, changing an option value, submitting an option or cancelling. Views subscribe through presenters and view models, so the visual layer never owns the navigation state.
When the player interacts with the UI, the menu service emits typed signals through the Event Dispatcher. The rest of the project reacts to those signals rather than calling into the menu prefab directly. You can swap the prefab, restyle the screen or change the navigation order without touching the gameplay code that responds to menu submissions.
Transitions between menu views are described by their own use case, so opening a sub-menu, going back or jumping to a sibling view is not a custom script per screen. The same menu definition can drive a main menu, a pause menu or any in-game overlay because the rules live in the data, not in the prefab.
How it fits into Serenity
The Menu System is part of the Application layer in the Serenity.Menu namespace and uses Domain interfaces such as IMenuSettingsDefinition to describe configuration. The infrastructure layer provides Unity implementations of the service, view factories and presenters. A dedicated installer registers all of this so the rest of the project can resolve menus through interfaces.
Menus do not exist in isolation. They depend on UI Themes for shared visuals and sound feedback, on Localization for labels, on the Input System for navigation, on the Event Dispatcher for outbound signals and on the Modal System for confirmation flows. Game Mode transitions can open or close menus when the game enters or leaves a state. This keeps the menu code focused on selection and transition logic, while presentation, input and language come from systems that are already wired together.
Because each layer is described through interfaces, swapping any piece is a matter of registering a different implementation in the installer. You can replace the view factory to introduce a custom rendering, replace the presenter to add analytics, or swap the menu service entirely in tests. The configuration assets stay the same, which means existing menu definitions keep working when the implementation changes.
Practical workflow
- Create a menu settings definition asset for the screen you want to build, for example a pause menu or a settings menu.
- Add the options, default values and target views or transitions inside the definition.
- Assign the menu view prefab and connect it to the shared UI theme used by the rest of the UI.
- Let the menu installer register the service and factories during the initialization pipeline.
- React to outbound signals such as OnMenuSubmitOptionSignal in the systems that should respond to player choices.
- Iterate on options, ordering and visuals from the definition asset without changing scene wiring.
What you get
- Declarative menu definitions described as ScriptableObject-based assets
- Menu use cases for selecting, changing value, submitting and cancelling options
- Transition use case MenuTransitionateToView for moving between sub-views
- Outbound signals such as OnMenuSubmitOptionSignal routed through the Event Dispatcher
- View, presenter and view model factories that keep the visual layer replaceable
- Service factory IMenuServiceFactory so the menu service itself can be swapped
- Shared UI theme integration so menus do not duplicate visual styling
- Localization integration for menu labels and option text
- Compatible with the Input System for keyboard, gamepad and pointer navigation
- Installers that register the system once for the entire project
- Clean separation between Domain, Application and Infrastructure layers
When to use this
- Projects that have more than one menu screen and need consistent visuals and behavior across them.
- Teams that want to localize and restyle menus without editing scene prefabs.
- Games that need pause, settings and in-game menus to share the same input, audio and theme conventions.
- Codebases moving away from direct UnityEvent button wiring toward a typed signal flow.
- Projects where menu navigation should be testable in isolation from Unity scenes.
Related systems
Use Serenity when you want a menu system that already speaks to themes, localization, input and events, but stays configurable from your own Unity project.
English
Español
Català