137 lines
12 KiB
Markdown
137 lines
12 KiB
Markdown
|
|
# **Game UI/UX Architecture & Routing Specification (Unity UI Toolkit Edition)**
|
||
|
|
|
||
|
|
This document outlines the complete structural layout, visual design, animations, and routing logic for the game's user interface, specifically optimized for **Unity UI Toolkit**. It serves as a direct guide for the associated .uxml, .uss, and .cs controller files.
|
||
|
|
|
||
|
|
## **1\. Global Design System & Technical Approach**
|
||
|
|
|
||
|
|
To maintain consistency and reduce development overhead, the UI is built using UXML templates, styled with USS, and driven by specific C\# controllers mapped to your project structure.
|
||
|
|
|
||
|
|
### **Core UI Toolkit Architecture & File Mapping**
|
||
|
|
|
||
|
|
* **Controllers:** UI logic is managed by dedicated scripts (UIManager.cs, MainMenuController.cs, LobbyController.cs, ProfileController.cs, SettingsController.cs, HUDController.cs).
|
||
|
|
* **Views (UXML):** Layouts are defined in modular files (MainMenu.uxml, Lobby.uxml, Profile.uxml, Settings.uxml, MainGameHUD.uxml).
|
||
|
|
* **Styles (USS):** Global styling is handled in Global.uss.
|
||
|
|
|
||
|
|
### **Reusable UI Components & Visual Styles**
|
||
|
|
|
||
|
|
* **Cursorless Navigation (Focus-Based Selection):** The game does not display a standard OS cursor (Cursor.visible \= false). Instead, the UI interprets mouse movement natively to determine focus. As the hidden cursor moves, the nearest interactive element highlights and scales up. This provides a smart, "snapping" feel to UI selection without needing a visible pointer.
|
||
|
|
* **The "Osu-Style" Slanted Button:** A custom VisualElement utilizing USS transform: skew(...) properties to create angled edges. Contains an inner text element counter-skewed to remain horizontal.
|
||
|
|
* **Diagonal Split-Screen Container:** Used in Lobby and Profile screens. Instead of a boring vertical line, the split is a sharp diagonal line (like a lightning slash).
|
||
|
|
* *Implementation:* Achieved by applying a negative skew to the Right Pane's parent container, and a positive skew to its inner content to keep text readable.
|
||
|
|
* *Left Pane (approx. 60% width):* Transparent background, showing the Unity 3D Camera rendering the character model and procedural map.
|
||
|
|
* *Right Pane (approx. 40% width):* Frosted glass effect.
|
||
|
|
* **Right-Pane Navigation Bar (Top):** Unlike standard top bars, the navigation is contained *entirely within the Right Pane*.
|
||
|
|
* \[ \< Back \] button is pinned to the Top-Left of the right panel.
|
||
|
|
* \[ Settings \] button is pinned to the Top-Right of the right panel.
|
||
|
|
* **Modal Overlay Backdrop:** A full-screen VisualElement with a semi-transparent black USS background. Used to dim the screen and block inputs behind the Settings panel, Password Prompts, and Confirmation Dialogs.
|
||
|
|
|
||
|
|
## **2\. Screen-by-Screen Implementation Details**
|
||
|
|
|
||
|
|
### **2.1. Main Menu (MainMenu.uxml & MainMenuController.cs)**
|
||
|
|
|
||
|
|
Inspired by osu\!lazer, this screen is highly dynamic and relies on smooth, physics-based transitions.
|
||
|
|
|
||
|
|
* **State 1: Initial Load (Idle)**
|
||
|
|
* **Visuals:** The background is a heavily blurred, atmospheric map preview. The OS cursor is hidden. Dead center is the **Beat Logo**.
|
||
|
|
* **Animation:** The Beat Logo dynamically pulses (scales up and down) precisely in sync with the audio source's beat/BPM. There are no other UI elements visible.
|
||
|
|
* **State 2: Active Menu (Transition & Active State)**
|
||
|
|
* **Interaction:** The user moves the mouse toward the center, the logo snaps into focus (glows), and they click.
|
||
|
|
* **Smooth Transition:** 1\. The Beat Logo shrinks slightly and smoothly translates from the dead center to its designated position in the horizontal menu row.
|
||
|
|
2\. A horizontal VisualElement container (the ribbon) unfolds from behind the logo using an elastic/spring animation.
|
||
|
|
3\. The slanted buttons slide out from the logo's position horizontally: \[Settings\] to the left, and \[Create Room\], \[Join Room\], \[Profile\], \[Exit\] to the right. They fade in (opacity: 1\) with a staggered C\# coroutine delay to create a cascading reveal effect.
|
||
|
|
|
||
|
|
### **2.2. Lobby (Lobby.uxml & LobbyController.cs)**
|
||
|
|
|
||
|
|
* **View Setup:** Utilizes the Diagonal Split-Screen Container. The view is dynamic; the Right Pane content switches based on whether the user selected "Join Room" or "Create Room" from the Main Menu.
|
||
|
|
* **Left Pane (Transparent):** Shows the player model and live procedural background map generation.
|
||
|
|
* **Right Pane (Static UI Area) \- Divided into Two Stages:**
|
||
|
|
* **Navigation (Shared):** \[ \< Back \] (Top-Left) and \[ Settings \] (Top-Right) are always visible.
|
||
|
|
* **Stage 1: Join Room (Room Browser)**
|
||
|
|
* *Triggered when entering via the \[Join Room\] button.*
|
||
|
|
* **Filters & Search:** The top of this view includes a TextField for **Searching** by Room Name, and a DropdownField (or sort icons) for **Sorting** the list (e.g., by Ping, Name, or Open Slots).
|
||
|
|
* **Room List:** A ScrollView dynamically populated with active rooms via C\#. Each list item displays the Room Name, Host Name, Ping, and a clear "Lock" icon if the room requires a password.
|
||
|
|
* **Interaction Logic:**
|
||
|
|
* Clicking an unlocked room immediately joins it and transitions the player to the Lounge.
|
||
|
|
* Clicking a locked room triggers a Modal Overlay popup asking for the password (contains a TextField and \[Submit\] / \[Cancel\] buttons) before joining.
|
||
|
|
* **Stage 2: Create Room (Configuration Setup)**
|
||
|
|
* *Triggered when entering via the \[Create Room\] button.*
|
||
|
|
* **Content:** Dedicated input fields for setting up a new session. Uses TextField for Room Name and an optional Password. *Note: Max players is strictly locked to 2, so no dropdown field is necessary.*
|
||
|
|
* **Toggles:** A "Require password to join" checkbox/toggle is present to enable or disable the password field.
|
||
|
|
* **Action:** A large "CREATE ROOM" button sits at the bottom. Clicking this instantiates the room on the server and transitions the player to the Lounge as the Host.
|
||
|
|
|
||
|
|
### **2.3. Profile (Profile.uxml & ProfileController.cs)**
|
||
|
|
|
||
|
|
* **Layout:** Reuses the Diagonal Split-Screen structure. The 3D camera shifts to a "Profile Studio" lighting setup for the Left Pane.
|
||
|
|
* **Right Pane Content:**
|
||
|
|
* **Navigation:** \[ \< Back \] (Top-Left) and \[ Settings \] (Top-Right).
|
||
|
|
* **Header:** Player Avatar (circular mask), Username, and Rank/Level badge.
|
||
|
|
* **Statistics:** Text labels and progress bars for Win Rate, Matches Played, and current Elo/Rating.
|
||
|
|
* **Customization:** A scrollable grid view at the bottom for equipping character skins or banners.
|
||
|
|
|
||
|
|
### **2.4. Lounge / Pre-Match (Lobby.uxml extensions or new UXML)**
|
||
|
|
|
||
|
|
Since the game is strictly 2-player, the Lounge is an intimate VS screen.
|
||
|
|
|
||
|
|
* **Layout:** The screen is split directly down the middle via a diagonal slash. Player 1 (Host) is on the left, Player 2 (Guest) is on the right.
|
||
|
|
* **Visuals:** Each half has a distinctly tinted background color (e.g., Blue for Host, Red/Orange for Guest) behind the transparent 3D character models.
|
||
|
|
* **Navigation:** \[ \< Back \] (Top-Left) and \[ Settings \] (Top-Right) overlay the entire screen.
|
||
|
|
* **Confirmation Logic:** Clicking \[ \< Back \] triggers a Modal Overlay popup: "Are you sure you want to leave the room? \[Yes\] \[No\]".
|
||
|
|
* **Ready System:**
|
||
|
|
* Bottom of each player's panel has a Ready toggle.
|
||
|
|
* The Host has a large \[ START GAME \] button in the bottom center.
|
||
|
|
* **Logic:** The \[ START GAME \] button is greyed out (SetEnabled(false)) until *both* players have toggled their status to "Ready".
|
||
|
|
|
||
|
|
### **2.5. In-Game HUD (MainGameHUD.uxml & HUDController.cs)**
|
||
|
|
|
||
|
|
The HUD strictly follows a "Zero Obstruction" philosophy with specific interactive zones.
|
||
|
|
|
||
|
|
* **Area 1: The 3D World (Background)**
|
||
|
|
* The root UI element is fully transparent and set to picking-mode: ignore so all mouse inputs register for aiming/gameplay.
|
||
|
|
* **Area 2: Player Stats (Top Left)**
|
||
|
|
* **Visuals:** Liquid progress bars for Health and Stamina. Instead of standard flat bars, these utilize a UI Toolkit custom shader or animated sprite mask to look like fluid filling/draining from a container.
|
||
|
|
* **Area 3: Minimap (Top Right)**
|
||
|
|
* **Visuals:** The minimap continuously updates based on player position. It features a soft fade effect at its borders (achieved via an alpha gradient mask/texture applied to the VisualElement), seamlessly blending it into the gameplay view without harsh square borders.
|
||
|
|
* **Area 4: Inventory (Bottom Left)**
|
||
|
|
* **Structure:** 4 distinct slots: \[ Current Holding \] (larger, highlighted), and three quick-slots \[ I \], \[ II \], \[ III \].
|
||
|
|
* **Logic:** Pressing 1, 2, or 3 on the keyboard fires an event in HUDController.cs. The selected item's icon swaps into the \[ Current Holding \] slot, and the index updates visually to show what is equipped.
|
||
|
|
* **Area 5: Game Info (Bottom Center)**
|
||
|
|
* **Visuals:** Minimalist text displaying current Ping (ms) and FPS.
|
||
|
|
* **Auto-Hide Logic:**
|
||
|
|
* To maximize visibility, Area 2 (Stats), Area 4 (Inventory), and Area 5 (Game Info) dynamically fade out.
|
||
|
|
* In HUDController.cs, track input activity (mouse movement, ability use, damage taken). If Time.time \- lastActivityTime \> 5f (5 seconds), tween the opacity of these areas to 0 or 0.2. Any new interaction instantly fades them back to 1\.
|
||
|
|
|
||
|
|
### **2.6. Settings Menu (Settings.uxml & SettingsController.cs)**
|
||
|
|
|
||
|
|
* **Structure:** A floating, centered panel (e.g., occupies roughly 60% width and 70% height) rather than a full-screen view. It sits on top of a full-screen semi-transparent backdrop that blocks interactions with the underlying UI.
|
||
|
|
* **Global Shortcut:** The Settings menu can be toggled open or closed from anywhere in the game by pressing **Ctrl \+ O**.
|
||
|
|
* **Visuals:** The panel has rounded corners and distinct styling to elevate it from the background.
|
||
|
|
* **Layout:** Standard settings configuration (Audio sliders, Graphics toggles) using UI Toolkit elements, with a prominent \[ X Close \] button in the top right corner of the panel.
|
||
|
|
|
||
|
|
## **3\. C\# State Machine & Routing Logic (UIManager.cs)**
|
||
|
|
|
||
|
|
To manage UXML templates, UIManager.cs controls the flow using a stack-based approach.
|
||
|
|
\[Game Launch\]
|
||
|
|
|
|
||
|
|
\[Main Menu (Idle \-\> Active Logo Bar)\]
|
||
|
|
|
|
||
|
|
\+-------------------+-------------------+-------------------+
|
||
|
|
| | | |
|
||
|
|
v v v v
|
||
|
|
\[Lobby: Create\] \[Lobby: Join\] \[Profile\] \[Settings (Overlay)\]
|
||
|
|
| | | |
|
||
|
|
v v | |
|
||
|
|
\[Lounge (Host)\] \[Lounge (Guest)\] \+---(Back)----------+
|
||
|
|
| |
|
||
|
|
\+--- \[All Ready\] \---+
|
||
|
|
|
|
||
|
|
(Host Clicks Start)
|
||
|
|
|
|
||
|
|
v
|
||
|
|
\[IN-GAME HUD\]
|
||
|
|
|
||
|
|
### **UI Toolkit State Management Implementation**
|
||
|
|
|
||
|
|
1. **Screen Controller Pattern:** Each controller (MainMenuController, LobbyController, etc.) holds a reference to its root VisualElement defined in its corresponding .uxml file.
|
||
|
|
2. **Navigation Stack (Stack\<VisualElement\>):** UIManager.cs pushes screens to this stack. Pressing the Top-Left \[ \< Back \] button calls a method to pop the current state, hiding it (display: none) and showing the previous one (display: flex).
|
||
|
|
3. **Global Action Listeners (Ctrl \+ O):** UIManager.cs actively listens to the input system for Ctrl \+ O to instantly trigger SettingsController.ToggleSettings() without affecting the current navigation stack path.
|
||
|
|
4. **Cursorless Input Routing:** UIManager.cs constantly monitors Input.mousePosition. It calculates the nearest interactive element within the active screen and applies a .hover USS class to it, overriding default Unity pointer events.
|