This guide explains the components in Sentinal, what each one owns, and when to use it. Sentinal is split into a small core router and optional Unity Input System helpers.
- View: A UGUI screen, panel, modal, HUD, or tab page with a
ViewSelector. - Current view: The focused view chosen by highest priority, then most recent open order.
- Root view: A persistent view that should not be closed by normal back/cancel navigation.
- Address: A
ViewAddressScriptableObject used to open a view without a direct scene reference. - Group: A
ViewGroupMaskchannel used to isolate menus, overlays, HUDs, and popups from each other.
Scope: global static router
Add to GameObject: no
SentinalViewRouter owns the active view history, current-view resolution, close/open operations, hidden-view restoration, and router events. Views register themselves when enabled, so you do not need a manager prefab in the scene.
Use it when code needs to open a known address, close the current modal, close a group of views, or inspect the current stack.
SentinalViewRouter.OpenView(settingsAddress);
SentinalViewRouter.CloseCurrentView();
SentinalViewRouter.CloseAllViews(excludeRootViews: true);
Debug.Log(SentinalViewRouter.GetDebugString());Key members:
| Member | Purpose |
|---|---|
CurrentView |
Focused view based on priority and recency. |
MostRecentView |
Last view added to history. |
OpenView(ViewAddress) |
Resolves and opens a view through a ViewAddress. |
CloseCurrentView() |
Closes the focused view unless it is a root view. |
CloseAllViews(...) |
Closes all views, optionally filtered by group and root status. |
HideAllViews(...) / RestoreHiddenViews(...) |
Temporarily hide and restore matching views. |
OnAdd, OnRemove, OnSwitch |
Events for UI state, debug tools, and input helpers. |
Scope: one routable UGUI view
Add to GameObject: yes, on the root of a menu/panel/screen
ViewSelector makes a GameObject part of Sentinal routing.
Common inspector fields:
| Field | Use |
|---|---|
| Address | Optional ViewAddress for decoupled routing. |
| Priority | Higher priority wins focus over lower priority views. Equal priority uses recency. |
| Track View | Adds the view to router history while active. Disable for purely local/tab sub-panels. |
| Root View | Prevents cancel/back from auto-closing persistent screens. |
| Group Mask | Assigns the view to one or more routing groups. |
| Exclusive View | Closes other matching non-root views when this view opens. |
| Hide Other Views | Temporarily hides matching views and restores them when this view closes. |
| First Selected | Selectable control focused when the view becomes current. |
| Prevent Selection | Clears selection for views driven only by input actions. |
| Remember Last Selected | Restores the last selected child control when focus returns. |
| Select On Enable | Selects on the next frame after activation. |
Typical usage:
public ViewSelector pauseMenu;
public void TogglePause()
{
if (pauseMenu.gameObject.activeSelf)
pauseMenu.Close();
else
pauseMenu.Open();
}Scope: ScriptableObject lookup key
Create menu: Assets > Create > Sentinal > View Address
ViewAddress lets gameplay or UI code open a view without storing a scene hierarchy reference. Assign the same asset to a ViewSelector, then call SentinalViewRouter.OpenView(address).
Use addresses for:
- Main menu destinations.
- Settings, credits, profile, and confirmation screens.
- Prefab-backed views that may be spawned or resolved at runtime.
Scope: button-level navigation helper
Add to GameObject: UGUI Button
ViewLink opens a ViewAddress from a standard button click. It is the no-code path for menu buttons such as Settings, Back to Lobby, or Open Profile.
Scope: shared group configuration and per-view group mask
Groups keep different UI layers independent. For example, a pause menu can close gameplay-menu views without touching the chat overlay or scoreboard.
Use separate groups for surfaces with different lifecycles:
| Group example | Typical views |
|---|---|
GameplayHud |
health, score, objective, match timer |
PauseMenu |
pause root, settings, quit confirmation |
Popup |
confirmation dialogs, invite prompts, warnings |
Lobby |
player cards, ready screen, mode picker |
ViewGroupMask supports bitwise-style group checks and exposes Everything / Nothing presets.
These components compile when Unity's Input System is enabled.
Scope: global static player registry
Add to GameObject: no
SentinalPlayer maps logical UI roles to PlayerInput instances. This is useful for local multiplayer, split-screen, and controller reassignment because UI components can target "primary player" or a numbered key without knowing where the runtime player object lives.
SentinalPlayer.SetPrimaryPlayer(playerInput);
SentinalPlayer.SetPlayer(1, secondPlayerInput);
PlayerInput primary = SentinalPlayer.PrimaryPlayer;
PlayerInput playerTwo = SentinalPlayer.GetPlayer(1);Scope: per-view input handler
Add to GameObject: alongside ViewSelector
ViewInputSystemHandler enables or disables view-specific input behavior based on whether its ViewSelector is current.
Use it when a view owns input actions only while it has focus.
Scope: per-view action map gate
Add to GameObject: alongside ViewSelector
ActionMapGate applies action-map rules when its view becomes focused.
Targets:
| Target | Behavior |
|---|---|
| Primary | Applies to SentinalPlayer.PrimaryPlayer. |
| All Players | Applies to every PlayerInput in PlayerInput.all. |
| Specific Key | Applies to SentinalPlayer.GetPlayer(playerKey). |
Modes:
| Mode | Behavior |
|---|---|
| Configured | Applies explicit enable/disable/inherit rules per named action map. |
| Exclusive | Switches the target PlayerInput to one named map. |
Common examples:
- Pause menu: enable
UI, disable or stop listening toGameplay. - Modal prompt: exclusive
UI. - Lobby screen: apply to all joined players.
Scope: canvas/global cancel listener
Add to GameObject: persistent UI object or canvas
ViewDismissalInputHandler listens for a cancel/back action and closes the focused non-root view.
Use it for:
Escon keyboard.Bon Xbox-style controllers.Circleon PlayStation-style controllers.- Any
UI/Cancelaction in your Input Actions asset.
Group filtering lets different canvases or players close only the views they own.
Scope: one UGUI button
Add to GameObject: Button
InputActionButton invokes a button's onClick from an Input Action. It can trigger on press or release and can optionally send pointer down/up events so visual button states still respond.
Use it for controller shortcuts such as Ready, Start, Confirm, Randomize, or Open Details.
Scope: one UGUI button
Add to GameObject: Button
InputActionButtonHold invokes a button after the bound action is held for a configured duration. Use the progress events to drive a fill image, radial meter, or hold-to-confirm state.
Use it for destructive or high-commitment actions such as Leave Match, Delete Save, or Ready All.
Scope: tab group controller
Add to GameObject: tab container
TabbedView connects a list of Toggles to a list of ViewSelector panels. When a toggle becomes active, the matching panel is shown and the others are hidden.
Use it for settings categories, inventory pages, character tabs, or lobby panels.
Scope: input wrapper for TabbedView
Add to GameObject: with or near TabbedView
TabbedViewInputHandler binds input actions to TabbedView.Next() and TabbedView.Previous().
Use it for shoulder-button, bumper, trigger, or keyboard tab cycling.
Scope: TextMeshPro label
Add to GameObject: TextMeshProUGUI
DisplayInputString renders the display string for an Input Action binding. It can use the current PlayerInput control scheme so the label changes when the active device changes.
Use it for lightweight button prompts such as [Submit], [Cancel], or [Next Tab].
Scope: global text prompt gateway
Add to GameObject: depends on your presenter implementation
TextInputGateway is the shared entry point for modal text entry. Register a presenter once, then request prompts from gameplay or UI code without coupling fields to a specific modal prefab.
Use it for player names, room codes, chat snippets, reports, and any controller-friendly text entry flow.
Scope: button-backed text field
Add to GameObject: UGUI Button
PromptedTextField turns a normal button into a controller-friendly text field. Clicking the button opens TextInputGateway, stores the confirmed value, updates its label, and fires OnValueChanged.
Important fields:
| Field | Use |
|---|---|
| Value Text | TextMeshPro label that displays the stored value. |
| Header | Prompt title. |
| Placeholder | Prompt placeholder text. |
| Multiline | Requests a multiline prompt. |
| Max Length | Maximum accepted character count. |
| Empty Display Text | Label shown and stored when the value is empty. |
ViewSelectorViewLinkon destination buttonsViewDismissalInputHandleron the canvas
- HUD
ViewSelectormarked as Root View - Pause menu
ViewSelectorin aPauseMenugroup - Pause menu
ActionMapGate - Global
ViewDismissalInputHandler
- Register each
PlayerInputthroughSentinalPlayer - Lobby root
ViewSelector - Per-player views using
ActionMapGatewith Specific Key when needed InputActionButtonfor ready/confirm actionsDisplayInputStringfor current-device prompts
- Parent
TabbedView - One
Toggleper tab - One
ViewSelectorpanel per tab TabbedViewInputHandlerfor bumper/trigger navigation
| Symptom | Check |
|---|---|
| Nothing is selected when a view opens | Assign First Selected, ensure an EventSystem exists, and check Prevent Selection. |
| Back closes the wrong screen | Check view Priority, Root View, and ViewDismissalInputHandler group filtering. |
| A HUD disappears when opening a menu | Put HUD and menu in separate groups, or make sure the menu's Hide Other Views only targets the intended group. |
| A view cannot be opened by address | Confirm the ViewAddress asset is assigned to the ViewSelector, and that the view is registered or has a resolvable fallback. |
| Gameplay input still fires under menus | Add ActionMapGate to the focused menu and verify the target player selection. |
| Prompts do not open | Register a TextInputGateway presenter before using PromptedTextField. |





