|
| 1 | +# CycloneGames.UIFramework |
| 2 | + |
| 3 | +<div align="left">English | <a href="./README.SCH.md">简体中文</a></div> |
| 4 | + |
| 5 | +A simple, robust, and data-driven UI framework for Unity, designed for scalability and ease of use. It provides a clear architecture for managing UI windows, layers, and transitions, leveraging asynchronous loading and a decoupled animation system. |
| 6 | + |
| 7 | +## Core Architecture |
| 8 | + |
| 9 | +The framework is built upon several key components that work together to provide a comprehensive UI management solution. |
| 10 | + |
| 11 | +### 1. `UIService` (The Facade) |
| 12 | +This is the primary public API for interacting with the UI system. Game code should use the `UIService` to open and close windows, abstracting away the underlying complexity. It acts as a clean entry point and handles the initialization of the `UIManager`. |
| 13 | + |
| 14 | +### 2. `UIManager` (The Core) |
| 15 | +A persistent singleton that orchestrates the entire UI lifecycle. Its responsibilities include: |
| 16 | +- **Asynchronous Loading**: Loads `UIWindowConfiguration` and UI prefabs using `CycloneGames.AssetManagement`. |
| 17 | +- **Lifecycle Management**: Manages the creation, destruction, and state transitions of `UIWindow` instances. |
| 18 | +- **Resource Caching**: Implements an LRU cache for UI prefabs to optimize performance when reopening frequently used windows. |
| 19 | +- **Instantiation Throttling**: Limits the number of UI elements instantiated per frame to prevent performance spikes. |
| 20 | + |
| 21 | +### 3. `UIRoot` & `UILayer` (Scene Hierarchy) |
| 22 | +- **`UIRoot`**: A required component in your scene that acts as the root for all UI elements. It contains the UI Camera and manages all `UILayer`s. |
| 23 | +- **`UILayer`**: Represents a distinct rendering and input layer (e.g., `Menu`, `Dialogue`, `Notification`). Windows are added to specific layers, which control their sorting order and grouping. `UILayer`s are configured via `ScriptableObject` assets. |
| 24 | + |
| 25 | +### 4. `UIWindow` (The UI Unit) |
| 26 | +The base class for all UI panels, pages, or popups. Each `UIWindow` is a self-contained component with its own behavior and lifecycle, managed by a robust state machine: |
| 27 | +- **`Opening`**: The window is being created and its opening transition is playing. |
| 28 | +- **`Opened`**: The window is fully visible and interactive. |
| 29 | +- **`Closing`**: The window's closing transition is playing. |
| 30 | +- **`Closed`**: The window is hidden and ready to be destroyed. |
| 31 | + |
| 32 | +### 5. `UIWindowConfiguration` (Data-Driven Configuration) |
| 33 | +A `ScriptableObject` that defines the properties of a `UIWindow`. This data-driven approach decouples configuration from code, allowing designers to easily modify UI behavior without touching scripts. Key properties include: |
| 34 | +- The UI prefab to instantiate. |
| 35 | +- The `UILayer` the window belongs to. |
| 36 | + |
| 37 | +### 6. `IUIWindowTransitionDriver` (Decoupled Animations) |
| 38 | +An interface that defines how a window animates when opening and closing. This powerful abstraction allows you to implement transition logic using any animation system (e.g., Unity Animator, LitMotion, DOTween) and apply it to windows without modifying their core logic. |
| 39 | + |
| 40 | +## Features |
| 41 | + |
| 42 | +- **Asynchronous by Design**: All resource loading and instantiation operations are fully asynchronous using `UniTask`, ensuring a smooth, non-blocking user experience. |
| 43 | +- **Data-Driven**: Configure windows and layers with `ScriptableObject` assets for maximum flexibility and designer-friendliness. |
| 44 | +- **Robust State Management**: A formal state machine manages the lifecycle of each `UIWindow`, preventing common bugs and race conditions. |
| 45 | +- **Extensible Animation System**: Easily create and assign custom transition animations for windows. |
| 46 | +- **Service-Based Architecture**: Integrates seamlessly with other services like `AssetManagement`, `Factory`, and `Logger`. Perfectly compatible with DI/IoC. |
| 47 | +- **Performance-Minded**: Includes features like prefab caching and instantiation throttling to maintain high performance. |
| 48 | + |
| 49 | +## Dependencies |
| 50 | + |
| 51 | +- `com.cysharp.unitask` |
| 52 | +- `com.cyclone-games.assetmanagement` |
| 53 | +- `com.cyclone-games.factory` |
| 54 | +- `com.cyclone-games.logger` |
| 55 | +- `com.cyclone-games.service` |
| 56 | + |
| 57 | +## Quick Start Guide |
| 58 | + |
| 59 | +### 1. Scene Setup |
| 60 | +1. Find the `UIFramework.prefab` in package, place it in the scene or load it runtime, the `UIFramework.prefab` already contains UIRoot, UICamera,default Layers. |
| 61 | + |
| 62 | +### 2. Create `UILayer` Configurations |
| 63 | +1. In the Project window, right-click and select **Create > CycloneGames > UIFramework > UILayer Configuration**. |
| 64 | +2. Create configurations for each layer you need, for example: |
| 65 | + - `UILayer_Menu` |
| 66 | + - `UILayer_Dialogue` |
| 67 | + - `UILayer_Notification` |
| 68 | +3. Assign these `UILayer` assets to the `UIRoot`'s `Layer Configurations` list in the Inspector. |
| 69 | + |
| 70 | +### 3. Create a `UIWindow` |
| 71 | +1. **Create the Script**: Create a new C# script that inherits from `UIWindow`. For example, `MainMenuWindow.cs`. |
| 72 | + ```csharp |
| 73 | + using CycloneGames.UIFramework.Runtime; |
| 74 | + |
| 75 | + public class MainMenuWindow : UIWindow |
| 76 | + { |
| 77 | + // Add references to your UI elements (buttons, text, etc.) here |
| 78 | + } |
| 79 | + ``` |
| 80 | +2. **Create the Prefab**: Create a new UI `Canvas` or `Panel` in your scene. Add your `MainMenuWindow` component to its root `GameObject`. Design your UI, then save it as a prefab. |
| 81 | +3. **Create the Configuration**: Right-click in the Project window and select **Create > CycloneGames > UIFramework > UIWindow Configuration**. |
| 82 | + - Name it something descriptive, like `UIWindow_MainMenu`. |
| 83 | + - Assign your `MainMenuWindow` prefab to the `Window Prefab` field. |
| 84 | + - Assign the appropriate `UILayer` (e.g., `UILayer_Menu`) to the `Layer` field. |
| 85 | + |
| 86 | +### 4. Initialize and Use the `UIService` |
| 87 | +In your game's bootstrap or initialization logic, create and initialize the `UIService`. |
| 88 | + |
| 89 | +```csharp |
| 90 | +using CycloneGames.UIFramework.Runtime; |
| 91 | +using Cysharp.Threading.Tasks; |
| 92 | +using UnityEngine; |
| 93 | + |
| 94 | +public class GameInitializer : MonoBehaviour |
| 95 | +{ |
| 96 | + private IUIService uiService; |
| 97 | + |
| 98 | + async void Start() |
| 99 | + { |
| 100 | + // Assume other services (asset management, factory, etc.) are already initialized |
| 101 | + // and available through a service locator or dependency injection. |
| 102 | + var assetPathBuilderFactory = ...; // Get from your DI container |
| 103 | + var objectSpawner = ...; // Get from your DI container |
| 104 | + var mainCameraService = ...; // Get from your DI container |
| 105 | +
|
| 106 | + uiService = new UIService(); |
| 107 | + uiService.Initialize(assetPathBuilderFactory, objectSpawner, mainCameraService); |
| 108 | + |
| 109 | + // Now you can use the service |
| 110 | + OpenMainMenu(); |
| 111 | + } |
| 112 | + |
| 113 | + public async UniTask OpenMainMenu() |
| 114 | + { |
| 115 | + // "UIWindow_MainMenu" is the filename of your UIWindowConfiguration asset |
| 116 | + UIWindow window = await uiService.OpenUIAsync("UIWindow_MainMenu"); |
| 117 | + if (window is MainMenuWindow mainMenu) |
| 118 | + { |
| 119 | + // Interact with your specific window instance |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + public void CloseMainMenu() |
| 124 | + { |
| 125 | + uiService.CloseUI("UIWindow_MainMenu"); |
| 126 | + } |
| 127 | +} |
0 commit comments