Cleanup the card implementation, add some readme files and update namespaces

This commit is contained in:
Michal Adam Pikulski
2025-10-21 12:10:16 +02:00
parent af77e07f99
commit 2fb77e1040
19 changed files with 570 additions and 608 deletions

View File

@@ -1,114 +0,0 @@
# Card System Implementation Plan
## Current Implementation Analysis
### Data Layer
1. **CardData.cs**:
- Represents an instance of a card in the player's collection
- Contains unique ID, rarity, and copies owned
- Has a reference to its CardDefinition for display information
- Includes methods for rarity upgrades when collecting duplicates
- Well-structured with proper serialization support
2. **CardDefinition.cs**:
- ScriptableObject template for creating card instances
- Contains basic info (name, description), visuals, and collection data
- Provides helper methods like CreateCardData() and GetBackgroundColor()
- Supports different zones (AppleHills, Quarry, Forest, Mountain, Beach)
3. **CardSystemManager.cs**:
- Singleton manager for the card system
- Manages available card definitions and player inventory
- Includes event callbacks for booster packs and card collection
- Implements functionality for adding and opening booster packs
4. **CardInventory.cs**:
- Fully implemented management of the player's card collection
- Includes methods for adding cards and tracking booster packs
- Provides filtering methods for different card types
- Supports card lookup by various properties (zone, rarity)
5. **CardVisualConfig.cs**:
- ScriptableObject for configuring the visual appearance of cards
- Maps rarities to colors and zones to colors/shapes
- Uses dictionary lookups for efficient access
### UI Layer
1. **CardUIElement.cs**:
- Handles displaying a single card in the UI
- Updates visuals based on card data (rarity, zone)
- References UI elements like card name text, images, frames, etc.
2. **UIPageController.cs**:
- Manages UI page transitions with a stack-based navigation system
- Provides methods for pushing, popping, and clearing the page stack
- Uses events to notify when pages change
3. **UI Page Components**:
- **CardMenuPage.cs**: Main menu for card system navigation
- **AlbumViewPage.cs**: Simplified implementation that shows filtered cards in grid
- **BoosterOpeningPage.cs**: Interactive card reveal experience
- **CardAlbumUI.cs**: Main controller for the card system UI
- **UIPage.cs**: Base class for common page functionality
## Implementation Status
### Completed
1. **Complete CardInventory Implementation**:
- Full implementation with methods to manage the player's card collection
- Filtering, sorting, and organization features
- Integration with CardSystemManager
2. **Booster Pack Generation**:
- Logic to generate random booster packs with appropriate rarity distribution
- Methods for awarding booster packs to the player
- Events for notifying UI when booster packs are obtained
3. **Card Collection UI**:
- Simplified album browsing UI with filtering and sorting options
- Removed unnecessary card stack and slot system
- Updated AlbumViewPage to use TextMeshPro components
4. **Booster Pack Opening UI (In Progress)**:
- Implemented interactive card reveal system
- Added card back prefabs for clickable reveal experience
- Created flip animations and particle effects for card reveals
- Updated to support revealing three cards individually
### Still Needed
1. **Booster Opening UI Refinement**:
- Fine-tune animation timings and transitions
- Implement custom card back designs
- Add more visual/audio feedback for different rarities
2. **Save/Load System**:
- Implement persistence for the player's card collection
- Add autosave functionality for cards and booster packs
3. **Card Collection Statistics**:
- Add UI for tracking collection completion
- Implement achievements for collecting sets
## Next Steps
### 1. Complete the Booster Opening Experience
- Create proper card back prefab with appropriate design
- Test and refine the card reveal animations
- Ensure particle effects and sounds play correctly
### 2. Add Save/Load System
- Implement JSON serialization for CardInventory
- Add autosave triggers after obtaining new cards
- Create save/load methods in CardSystemManager
### 3. Polish the Overall Experience
- Add transition animations between pages
- Improve visual feedback for obtaining new cards
- Implement collection statistics display
### 4. Additional Features (Optional)
- Special collection bonuses for completing sets
- Card trading system with NPCs
- Card usage mechanics beyond collection

View File

@@ -1,159 +0,0 @@
# Card System Integration and Testing Guide
## Overview
This document outlines the integration between the data and UI layers of the Apple Hills card collection system, as well as the testing tools available for development purposes.
## Architecture Summary
The card system follows a clean separation of concerns:
1. **Data Layer** (Assets/Scripts/Data/CardSystem/)
- `CardSystemManager`: Singleton for managing card data, booster packs, and collection
- `CardInventory`: Player's collection of cards and booster packs
- `CardData`: Runtime instance of a collected card
- `CardDefinition`: ScriptableObject template defining card properties
- `CardVisualConfig`: Visual settings for cards based on rarity/zone
2. **UI Layer** (Assets/Scripts/UI/CardSystem/)
- `CardAlbumUI`: Main controller for the card UI system
- `UIPageController`: Stack-based navigation system
- `UIPage`: Base class for UI pages with transition animations
- Page Components:
- `CardMenuPage`: Main menu for the card system
- `AlbumViewPage`: Grid display of collected cards with filtering
- `BoosterOpeningPage`: Interactive card reveal experience
- `CardUIElement`: Individual card visual representation
- `BoosterNotificationDot`: UI element showing booster pack counts
## Integration Points
### Initialization Process
1. `CardSystemManager` initializes during the bootstrap process using `BootCompletionService`
2. UI components register with `BootCompletionService.RegisterInitAction()` for post-boot initialization
3. UI components access card data through `CardSystemManager.Instance`
### Data Flow
1. **Card Collection**:
- `CardSystemManager` manages the player's `CardInventory`
- Cards are added via `AddCardToInventory()`
- Card collection triggers `OnCardCollected` event
2. **Booster Packs**:
- Added via `CardSystemManager.AddBoosterPack()`
- Opened via `CardSystemManager.OpenBoosterPack()`
- Booster count changes trigger `OnBoosterCountChanged` event
- Opening boosters triggers `OnBoosterOpened` event
3. **Card Display**:
- `CardUIElement` displays a card using `SetupCard(cardData)`
- `AlbumViewPage` displays cards in a grid with filtering options
- `BoosterOpeningPage` handles interactive card reveals
### Event System
Key events that connect data and UI layers:
- `OnBoosterCountChanged`: Triggered when booster count changes
- `OnBoosterOpened`: Triggered when a booster is opened
- `OnCardCollected`: Triggered when a new card is added to collection
- `OnCardRarityUpgraded`: Triggered when duplicates upgrade a card's rarity
## Testing Tool: CardSystemTester
The `CardSystemTester` provides a simple interface for testing the card system without requiring full game integration.
### Features
- Adding booster packs
- Opening the card menu
- Opening booster packs
- Browsing the album view
- Generating random test cards
- Clearing the card collection
### Usage
1. Add `CardSystemTester` component to a GameObject in your test scene
2. Reference the `CardAlbumUI` component
3. Enter Play mode and use the inspector buttons
4. All buttons are disabled in edit mode
### Implementation Notes
```csharp
public class CardSystemTester : MonoBehaviour
{
// Only need reference to CardAlbumUI, the CardSystemManager is accessed via singleton
[SerializeField] private CardAlbumUI cardAlbumUI;
// Other variables for test configuration
[SerializeField] [Range(1, 10)] private int boosterPacksToAdd = 3;
[SerializeField] [Range(1, 100)] private int cardsToGenerate = 10;
// All operations use CardSystemManager.Instance
public void AddBoosterPacks() {
CardSystemManager.Instance.AddBoosterPack(boosterPacksToAdd);
// Other operations...
}
// Uses CardAlbumUI to simulate UI interactions
public void SimulateBackpackClick() {
// Trigger the backpack button's onClick event
}
// Additional test methods...
}
```
### Test Scene Setup
1. Create a new scene or use an existing test scene
2. Add a Canvas with proper UI configuration
3. Add the CardSystem prefab (containing CardAlbumUI)
4. Add the CardSystemTester component
5. Make sure you have card definitions configured
## Current Implementation Status
1. **Complete**:
- Core data management through `CardSystemManager`
- Card collection and inventory management
- Basic UI navigation system
- Booster pack opening flow
- Album view with filtering
2. **Added API Methods**:
- `GetAllCardDefinitions()`: Returns list of all card definitions
- `GetCardInventory()`: Returns reference to player's card inventory
- `ClearAllCards()`: Resets the player's collection
- Various utility methods for filtering and statistics
3. **UI Improvements**:
- Simplified card display in album view
- Properly integrated card reveal animations
- Back button functionality for all pages
## Known Issues and Considerations
1. **Performance**: Large collections may require optimization
2. **Save System**: Currently not implemented, needs integration with game save system
3. **Card Definition Loading**: Ensure card definitions are loaded before use
4. **Testing Workflow**: Test specific state scenarios using the CardSystemTester
5. **Animation Timing**: May need adjustment for smoother experience
## Next Steps
1. Implement save/load system for card collection
2. Add collection statistics display
3. Implement rarity-specific effects for card reveals
4. Create more comprehensive test coverage
## Technical References
- Bootstrap system: Use `BootCompletionService.RegisterInitAction(InitializePostBoot)` for initialization
- Data access: Always use `CardSystemManager.Instance` for data access
- Page navigation: Use `UIPageController.Instance.PushPage()` and `PopPage()`
- Card UI: Use `CardUIElement.SetupCard()` to configure card display

View File

@@ -0,0 +1,340 @@
# Apple Hills Card System Designer Playbook
This playbook is for designers working with the raritybased Card System in Apple Hills. It provides a highlevel architecture overview, fast TL;DR playbooks for common tasks (with code-first snippets), and deeper guidance on how the system fits together.
## Table of Contents
- [Architecture at a Glance](#architecture-at-a-glance)
- [TL;DR Playbooks (Code-First)](#tldr-playbooks-code-first)
- [Open Booster Packs](#open-booster-packs)
- [Grant a Specific Card](#grant-a-specific-card)
- [Query the Collection](#query-the-collection)
- [Configure Visuals by Code (optional)](#configure-visuals-by-code-optional)
- [Clear the Collection](#clear-the-collection)
- [Authoring with the Card Editor (No Manual Setup)](#authoring-with-the-card-editor-no-manual-setup)
- [What happens automatically (under the hood)](#what-happens-automatically-under-the-hood)
- [In-Depth Overview](#in-depth-overview)
- [Designer HowTos (Quick Reference)](#designer-how-tos-quick-reference)
- [Best Practices & Tips](#best-practices--tips)
- [Known Gaps](#known-gaps)
- [FAQ](#faq)
- [Technical Reference (Quick)](#technical-reference-quick)
- [Change Log](#change-log)
## Architecture at a Glance
The system is split into two main layers with clear responsibilities and a lightweight event bridge.
- Data Layer (`Assets/Scripts/Data/CardSystem`)
- `CardSystemManager` (singleton)
- Source of truth for all card definitions, booster logic, and player `CardInventory`.
- Emits events on collection changes and booster activity.
- `CardInventory`
- Players owned cards and booster pack counters.
- Utility APIs for filtering cards (by rarity, zone, etc.).
- `CardDefinition` (`ScriptableObject`)
- Authoring asset that defines a card (name, visuals, zone, rarity tiering).
- `CardData`
- Runtime instance of a card in the player collection (ID, rarity, copies owned, links back to `CardDefinition`).
- `CardVisualConfig` (`ScriptableObject`)
- Central mapping for rarity/zone → visual treatment (colors, frames, shapes).
- UI Layer (`Assets/Scripts/UI/CardSystem`)
- `CardAlbumUI`
- Entry point for the card UI (menu, album browser, booster opening).
- `UIPageController` + `UIPage`
- Stack-based navigation (push/pop) and shared transitions.
- Page Components
- `CardMenuPage` Card hub/menu
- `AlbumViewPage` Grid album view with filter/sort options
- `BoosterOpeningPage` Interactive three-card reveal
- `CardUIElement`
- Renders a single card using `CardData` and `CardVisualConfig`
- `BoosterNotificationDot`
- Shows available booster pack count
- Events (Data ↔ UI)
- `OnBoosterCountChanged`
- `OnBoosterOpened`
- `OnCardCollected`
- `OnCardRarityUpgraded`
- Lifecycle
- Initialize during boot: `BootCompletionService.RegisterInitAction(...)`
- `CardSystemManager.Instance` is the access point from UI and tools (e.g., `CardSystemTester`)
## TL;DR Playbooks (Code-First)
These are the most common tasks youll perform in code. Paste the snippets into a temporary test `MonoBehaviour`, a unit test, or hook them into your gameplay systems.
### Open Booster Packs
```csharp
using AppleHills.Data.CardSystem;
using UnityEngine;
public class BoosterOpenerSample : MonoBehaviour
{
private void Start()
{
// Subscribe to events (optional, for feedback/UI updates)
CardSystemManager.Instance.OnBoosterOpened += cards =>
{
Debug.Log($"Opened booster with {cards.Count} cards");
};
CardSystemManager.Instance.OnCardCollected += card =>
{
Debug.Log($"Collected: {card.Definition.Name} (rarity: {card.Rarity})");
};
CardSystemManager.Instance.OnCardRarityUpgraded += card =>
{
Debug.Log($"Upgraded rarity: {card.Definition.Name} -> {card.Rarity}");
};
// Give the player some boosters and open one
CardSystemManager.Instance.AddBoosterPack(1);
var revealed = CardSystemManager.Instance.OpenBoosterPack();
foreach (var cd in revealed)
{
Debug.Log($"Revealed: {cd.Definition.Name}");
}
}
}
```
### Grant a Specific Card
```csharp
using System.Linq;
using AppleHills.Data.CardSystem;
using UnityEngine;
public class GrantCardSample : MonoBehaviour
{
[SerializeField] private string cardName = "Apple Picker"; // example
private void Start()
{
var def = CardSystemManager.Instance
.GetAllCardDefinitions()
.FirstOrDefault(d => d.Name == cardName);
if (def == null)
{
Debug.LogWarning($"CardDefinition not found: {cardName}");
return;
}
var cardData = CardSystemManager.Instance.AddCardToInventory(def);
Debug.Log($"Granted: {cardData.Definition.Name} (copies: {cardData.CopiesOwned})");
}
}
```
### Query the Collection
```csharp
using AppleHills.Data.CardSystem;
using UnityEngine;
public class QueryCollectionSample : MonoBehaviour
{
private void Start()
{
var inv = CardSystemManager.Instance.GetCardInventory();
// All cards
var all = inv.GetAllCards();
Debug.Log($"Total cards owned: {all.Count}");
// By rarity (example)
var rares = inv.GetByRarity(CardRarity.Rare);
Debug.Log($"Rares: {rares.Count}");
// By zone (example)
var forest = inv.GetByZone(CardZone.Forest);
Debug.Log($"Forest: {forest.Count}");
// Counts (progression checks)
var byRarity = inv.CountByRarity();
var byZone = inv.CountByZone();
// Iterate dictionaries as needed
}
}
```
### Clear the Collection
```csharp
using AppleHills.Data.CardSystem;
using UnityEngine;
public class ClearCollectionSample : MonoBehaviour
{
private void Start()
{
CardSystemManager.Instance.ClearAllCards();
Debug.Log("Card collection cleared (dev/test only).");
}
}
```
## Authoring with the Card Editor (No Manual Setup)
Designers should use the dedicated editor window: `AppleHills/Card Editor`.
- Open via Unity menu: `AppleHills/Card Editor` (menu path defined in `CardEditorWindow`)
- The window provides a card list, detail editor, and a live preview of the UI card.
- You dont need to create folders or assets manually—the tool handles setup and discovery.
### What happens automatically (under the hood)
The `Assets/Editor/CardSystem/CardEditorWindow.cs` implements the following behaviors:
- Ensures the data directory exists: `Assets/Data/Cards` (creates it on first run).
- Discovers all `CardDefinition` assets under `Assets/Data/Cards` automatically via `AssetDatabase.FindAssets("t:CardDefinition")` and keeps the list sorted by `Name`.
- Creates new card assets as `Card_<Name>.asset` inside `Assets/Data/Cards`.
- Loads a UI preview prefab from `Assets/Prefabs/UI/Cards/SIngleCardDisplayUI.prefab` to render a live card preview inside the editor using `PreviewRenderUtility`.
- Tries to load `CardVisualConfig` at `Assets/Data/Cards/CardVisualConfig.asset` for consistent rarity/zone styling in the preview.
- Responds to Undo/Redo and Editor recompiles to stay in sync.
- When you duplicate or delete cards from the window, the corresponding assets are created/removed accordingly.
Result: Designers focus on content (name, description, zone, art, etc.) in the Card Editor. The system takes care of folders, discovery, previewing, and syncing definitions with runtime.
## In-Depth Overview
Data Layer Details
- `CardDefinition` (authoring)
- What it is: a `ScriptableObject` that defines a cards identity and static presentation (name, description, zone, default visuals).
- Typical fields: `Name`, `Description`, `Zone`, rarity metadata, sprites/textures, optional tags.
- Helpers: `CreateCardData()` to generate a runtime `CardData` instance for inventory.
- `CardData` (runtime instance)
- Purpose: Represents what the player owns unique ID, rarity state, copies owned.
- Behavior: When duplicates are collected, `CardData` may upgrade rarity (e.g., duplicate thresholds).
- Links: Holds reference to its `CardDefinition` for display and classification.
- `CardInventory` (player collection)
- Responsibilities: Store cards, track counts, support filters/lookups (by rarity/zone), manage booster counters.
- Common operations: `AddCard(def)`, `GetAllCards()`, `GetByRarity()`, `GetByZone()`, `CountByRarity()`, `CountByZone()`.
- Notes: Designed for efficiency and clarity; returns collections for the UI to display.
- `CardSystemManager` (singleton coordinator)
- Responsibilities: Owns `CardInventory`, holds the card definition catalog, controls booster generation/opening, exposes public APIs.
- Events: `OnBoosterCountChanged`, `OnBoosterOpened`, `OnCardCollected`, `OnCardRarityUpgraded`.
- Typical APIs:
- `GetAllCardDefinitions()``IReadOnlyList<CardDefinition>`
- `GetCardInventory()``CardInventory`
- `AddBoosterPack(int count)`
- `OpenBoosterPack()``List<CardData>` (or similar)
- `AddCardToInventory(CardDefinition def)`
- `ClearAllCards()`
- `CardVisualConfig` (visual mappings)
- Purpose: Central place to establish the brand/look per rarity and zone.
- Implementation: `ScriptableObject` with dictionaries for quick lookups by rarity/zone.
UI Layer Details
- `UIPageController` + `UIPage`
- Navigation: `PushPage(page)`, `PopPage()`, `Clear()`; optional transition animations.
- Pattern: Each page is a `UIPage` subclass registered under `CardAlbumUI`.
- `CardAlbumUI` (system entry)
- Role: Wires pages together, responds to `CardSystemManager` events, routes to `AlbumViewPage` or `BoosterOpeningPage`.
- `AlbumViewPage`
- Role: Displays a grid of `CardUIElement` items from `CardInventory` with filtering/sorting UI.
- Notes: Uses TextMeshPro components and simplified presentation (no stack/slot system).
- `BoosterOpeningPage`
- Role: Handles the interactive reveal flow for 3 cards per booster; flip animations, particle FX, rarity feedback.
- Notes: Timings and art are still under refinement; supports individual reveal clicks.
- `CardUIElement`
- Role: Displays a single `CardData` name, art, frame, rarity chips, zone styling.
- Data Source: Uses `CardVisualConfig` for color/frame mapping.
- `BoosterNotificationDot`
- Role: Indicates current booster count; listens to `OnBoosterCountChanged`.
Event Flow Examples
- Opening a booster
- Player code calls `CardSystemManager.OpenBoosterPack()` → generates/awards 3 cards → raises `OnBoosterOpened`.
- Inventory updated; for each card, `OnCardCollected` (and maybe `OnCardRarityUpgraded`) fires.
- `BoosterOpeningPage` animates reveals; `AlbumViewPage` updates when returning.
- Adding a card via quest reward
- Gameplay script calls `AddCardToInventory(def)`.
- Inventory updates; events fire to update UI.
Rarity & Duplicates
- The system tracks copies owned per card.
- Duplicates can trigger rarity upgrades based on thresholds (implemented in `CardData`).
- UI can react with special effects via `OnCardRarityUpgraded` (e.g., distinct VFX/SFX per rarity).
## Designer HowTos (Quick Reference)
Author a New Card (use the editor tool)
1) Open `AppleHills/Card Editor`.
2) Click New/Duplicate, edit `Name`, `Description`, `Zone`, and assign art.
3) Save—asset is created as `Assets/Data/Cards/Card_<Name>.asset`. Its auto-discovered by runtime.
Grant a Card by Code (quest reward)
```csharp
CardSystemManager.Instance.AddCardToInventory(rewardDefinition);
```
Open a Booster by Code
```csharp
CardSystemManager.Instance.AddBoosterPack(1);
CardSystemManager.Instance.OpenBoosterPack();
```
Filter Cards for a Page
```csharp
var inv = CardSystemManager.Instance.GetCardInventory();
var list = inv.GetByZone(CardZone.Quarry);
```
## Best Practices & Tips
- Always access data via `CardSystemManager.Instance` to keep a single source of truth.
- Keep `CardDefinition` assets lightweight and consistent; use tags/zones for filtering.
- When adding new rarities/zones, update `CardVisualConfig` and verify UI styling.
- For smoother reveals, coordinate with VFX/SFX to differentiate rarities.
- Large collections: consider paging or virtualized grids if performance becomes a concern.
## Known Gaps
- Save/Load not implemented test sessions wont persist player collection.
- Booster Opening polish (timings/art/audio) is ongoing.
- Collection statistics/achievements UI pending.
## FAQ
- Q: My new `CardDefinition` doesnt show up in the album.
- A: Ensure the asset is in `Assets/Data/Cards` (the editor tool places it there) and that definitions load before UI opens. Check the `CardSystemManager` discovery and your zones/rarities.
- Q: How do I trigger the card UI from another part of the game?
- A: Use `CardAlbumUI`s public entry points or route through your UI flow to push the relevant page via `UIPageController`.
- Q: Can I guarantee a specific rarity in a booster for a tutorial?
- A: Add a temporary tutorial hook in `CardSystemManager` to override booster generation rules for guided moments, or directly grant specific `CardDefinition`s for the tutorial step.
- Q: How do duplicates upgrade rarity?
- A: The logic lives in `CardData`; when copies cross thresholds, it fires `OnCardRarityUpgraded`. Coordinate with design to set thresholds and with UI to show feedback.
## Technical Reference (Quick)
- Initialize after boot: `BootCompletionService.RegisterInitAction(InitializePostBoot)`
- Data access: `CardSystemManager.Instance`
- Navigation: `UIPageController.Instance.PushPage()` / `PopPage()`
- Show a card in UI: `CardUIElement.SetupCard(cardData)`
- Test harness: `CardSystemTester` (add to scene, link `CardAlbumUI`)
## Change Log
- v1.1: Added Table of Contents, inline code formatting, code-first TL;DR playbooks, and an authoring section based on `CardEditorWindow`.
- v1.0: Initial designer playbook, aligned with Implementation Plan and Integration & Testing Guide.

View File

@@ -1,309 +0,0 @@
# Card System UI Setup Guide
This guide provides detailed instructions for setting up the Card System UI in Unity, organized into prefabs that can be easily maintained and modified.
## Prefab Structure Overview
The card system UI should be structured with a modular prefab approach:
1. **Main Card System Prefab** - Contains the CardAlbumUI component and core structure
2. **Individual UI Page Prefabs** - Each page as its own prefab
3. **Card UI Prefab** - For card display and interaction
## Detailed Prefab Structure
### Main CardSystem Prefab
```
CardSystem (with CardAlbumUI component)
├── BackpackIcon (GameObject)
│ ├── BackpackImage (Image)
│ ├── BoosterCountText (TextMeshProUGUI)
│ └── NotificationDot (GameObject with Image)
├── UIPageController (automatically added by CardAlbumUI if not present)
└── Notifications (GameObject)
└── NewCardNotification (GameObject)
├── Background (Image)
└── Text (TextMeshProUGUI)
```
### Page Prefabs
**1. MainMenuPage Prefab:**
```
MainMenuPage (with CardMenuPage component & CanvasGroup)
├── Background (Image)
├── Title (TextMeshProUGUI)
├── OpenBoosterButton (Button)
│ └── Text (TextMeshProUGUI)
├── ViewAlbumButton (Button)
│ └── Text (TextMeshProUGUI)
├── ChangeClothesButton (Button)
│ └── Text (TextMeshProUGUI)
└── NoBoostersMessage (GameObject)
└── Text (TextMeshProUGUI)
```
**2. AlbumViewPage Prefab:**
```
AlbumViewPage (with AlbumViewPage component & CanvasGroup)
├── Background (Image)
├── FilterPanel (GameObject)
│ ├── ZoneFilterDropdown (TMP_Dropdown)
│ │ ├── Label (TextMeshProUGUI)
│ │ └── Arrow (Image)
│ ├── RarityFilterDropdown (TMP_Dropdown)
│ │ ├── Label (TextMeshProUGUI)
│ │ └── Arrow (Image)
│ └── ResetFiltersButton (Button)
│ └── Text (TextMeshProUGUI)
├── AlbumScrollView (ScrollRect)
│ └── AlbumGrid (GridLayoutGroup)
```
**3. BoosterOpeningPage Prefab:**
```
BoosterOpeningPage (with BoosterOpeningPage component & CanvasGroup)
├── Background (Image)
├── BoosterPackObject (GameObject)
│ └── BoosterImage (Image)
├── CardRevealContainer (RectTransform)
│ ├── CardRevealPosition1 (Transform)
│ ├── CardRevealPosition2 (Transform)
│ └── CardRevealPosition3 (Transform)
├── OpenBoosterButton (Button)
│ └── Text (TextMeshProUGUI)
├── ContinueButton (Button)
│ └── Text (TextMeshProUGUI)
├── CardRevealSound (AudioSource)
├── RareCardSound (AudioSource)
├── CardRevealParticles (ParticleSystem)
└── RareCardParticles (ParticleSystem)
```
### Card-Related Prefabs
**1. CardPrefab:**
```
Card (with CardUIElement component & Button)
├── CardBackground (Image)
├── CardFrame (Image)
├── CardImage (Image)
├── CardNameText (TextMeshProUGUI)
├── CardDescriptionText (TextMeshProUGUI)
├── ZoneLabel (TextMeshProUGUI)
└── RarityIndicator (Image)
```
**2. CardBackPrefab:**
```
CardBack (with Button component)
├── CardBackImage (Image)
└── BackDesign (Image)
```
## Component Setup Guide
### CardAlbumUI Component Setup
This is the central controller for the card system:
```
CardAlbumUI Component Inspector:
- UI References:
- Backpack Icon: [BackpackIcon GameObject]
- Main Menu Page: [MainMenuPage Prefab]
- Album View Page: [AlbumViewPage Prefab]
- Booster Opening Page: [BoosterOpeningPage Prefab]
- UI Elements:
- Backpack Button: [BackpackIcon Button Component]
- Booster Count Text: [BoosterCountText Component]
- Notification Dot: [NotificationDot GameObject]
- Backpack Animation Target: [BackpackIcon Transform]
- New Card Notification: [NewCardNotification GameObject]
- Notification Settings:
- Notification Duration: 3 seconds (adjustable)
- Notification Sound: [AudioSource Component]
```
### CardMenuPage Component Setup
```
CardMenuPage Component Inspector:
- Menu Options:
- Open Booster Button: [OpenBoosterButton]
- View Album Button: [ViewAlbumButton]
- Change Clothes Button: [ChangeClothesButton]
- UI Elements:
- Booster Count Text: [BoosterCountText]
- No Boosters Message: [NoBoostersMessage]
- Canvas Group: [CanvasGroup on this GameObject]
```
### AlbumViewPage Component Setup
```
AlbumViewPage Component Inspector:
- Album UI Elements:
- Album Grid: [AlbumGrid Component]
- Card Prefab: [CardPrefab Asset]
- Filter UI:
- Zone Filter Dropdown: [ZoneFilterDropdown]
- Rarity Filter Dropdown: [RarityFilterDropdown]
- Reset Filters Button: [ResetFiltersButton]
- Canvas Group: [CanvasGroup on this GameObject]
```
### BoosterOpeningPage Component Setup
```
BoosterOpeningPage Component Inspector:
- UI Elements:
- Booster Pack Object: [BoosterPackObject]
- Card Reveal Container: [CardRevealContainer]
- Card Reveal Positions: [Array of 3 Transform positions]
- Card Prefab: [CardPrefab Asset]
- Card Back Prefab: [CardBackPrefab Asset]
- Open Booster Button: [OpenBoosterButton]
- Continue Button: [ContinueButton]
- Canvas Group: [CanvasGroup on this GameObject]
- Open Booster Text: [TextMeshProUGUI]
- Continue Text: [TextMeshProUGUI]
- Animation Settings:
- Card Reveal Delay: 0.3 (adjustable)
- Card Move To Backpack Delay: 0.8 (adjustable)
- Flip Animation Duration: 0.5 (adjustable)
- Backpack Target Transform: [BackpackIcon Transform]
- Card Reveal Sound: [CardRevealSound Component]
- Rare Card Sound: [RareCardSound Component]
- Card Reveal Particles: [CardRevealParticles Component]
- Rare Card Particles: [RareCardParticles Component]
```
### CardUIElement Component Setup
```
CardUIElement Component Inspector:
- Card UI Elements:
- Card Background Image: [CardBackground Image]
- Card Frame Image: [CardFrame Image]
- Card Image: [CardImage]
- Card Name Text: [CardNameText]
- Card Description Text: [CardDescriptionText]
- Zone Label: [ZoneLabel Text]
- Rarity Label: [RarityIndicator Image]
```
## Prefab Creation Process
### 1. Create Card-Related Prefabs First
Start by creating the card prefabs since other prefabs will reference them:
1. **Create CardPrefab**:
- Create GameObject → UI → Image (for background)
- Add child Images for frame and card art
- Add TextMeshPro components for name, description, zone
- Add CardUIElement script
- Configure Inspector references
- Add Button component
- Save as prefab
2. **Create CardBackPrefab**:
- Create GameObject → UI → Image (for card back)
- Add Button component for interaction
- Style appropriately to match your game's aesthetics
- Save as prefab
### 2. Create UI Page Prefabs
Create each page prefab individually:
1. **Create MainMenuPage Prefab**:
- Set up UI elements as shown in structure
- Add CardMenuPage script
- Add CanvasGroup component
- Configure all Inspector references
- Save as prefab
2. **Create AlbumViewPage Prefab**:
- Set up UI elements as shown in structure
- Add AlbumViewPage script
- Add CanvasGroup component
- Configure all Inspector references
- Assign CardPrefab
- Save as prefab
3. **Create BoosterOpeningPage Prefab**:
- Set up UI elements as shown in structure
- Create CardRevealContainer with three child positions
- Add BoosterOpeningPage script
- Add CanvasGroup component
- Add audio sources and particle systems
- Configure all Inspector references
- Assign CardPrefab and CardBackPrefab
- Save as prefab
### 3. Create Main CardSystem Prefab
Finally, create the main controller prefab:
1. **Create CardSystem GameObject**:
- Add CardAlbumUI script
- Set up BackpackIcon and Notifications as shown in structure
- Assign references to page prefabs (not instances)
- Configure all Inspector references
- Save as prefab
## Scene Setup Instructions
### 1. Add CardSystem to Your Scene
1. Drag the CardSystem prefab into your scene
2. Make sure it's on the UI layer
3. Verify it has a Canvas component if needed (or is under a Canvas)
### 2. Configure the CardSystemManager
1. Create a GameObject named "CardSystemManager" if not already present
2. Add the CardSystemManager script
3. Populate it with some test card definitions
4. Ensure it's marked as DontDestroyOnLoad if needed
### 3. Test the System
1. Enter Play mode
2. Test clicking the backpack icon
3. Add test booster packs: `CardSystemManager.Instance.AddBoosterPack(3)`
4. Test opening boosters and viewing the album
## Additional Tips
1. **Canvas Settings**:
- Set your Canvas to Screen Space - Overlay
- Use Scale With Screen Size with reference resolution 1920x1080
- Configure the Canvas Scaler for proper UI scaling
2. **UI Navigation**:
- Configure button navigation for keyboard/controller support
- Set tab order for accessibility
3. **Audio Setup**:
- Keep audio sources on the respective UI elements
- Adjust spatial blend to 0 (2D) for UI sounds
- Use appropriate volume for notification sounds
4. **Animation Considerations**:
- All animations use Pixelplacement.Tween
- Adjust animation durations in Inspector for fine-tuning
- Consider creating animation presets for consistent feel
5. **Testing on Different Devices**:
- Test the UI on different aspect ratios
- Ensure UI elements are anchored properly for different resolutions
- Use the Device Simulator to test mobile layouts if targeting mobile
6. **Performance Tips**:
- Consider object pooling for cards in large collections
- Disable raycast targets on non-interactive elements
- Use sprite atlases for card images

194
docs/ui_page_navigation.md Normal file
View File

@@ -0,0 +1,194 @@
# UI Page Navigation System
A brief guide to the stack-based page navigation used across the project. It is built around `UIPageController` (the navigator) and `UIPage` (the base page with transition hooks). This system is used by the card collection UI and can be reused for any feature that needs push/pop navigation with transitions.
- Source files:
- `Assets/Scripts/UI/Core/UIPageController.cs`
- `Assets/Scripts/UI/Core/UIPage.cs`
## Table of Contents
- [Concepts](#concepts)
- [Quick Start](#quick-start)
- [Transitions and Events](#transitions-and-events)
- [Card System Case Studies](#card-system-case-studies)
- [Best Practices](#best-practices)
- [API Reference (Essentials)](#api-reference-essentials)
## Concepts
- `UIPageController`
- A singleton navigator that maintains a stack of `UIPage` instances.
- Provides `PushPage`, `PopPage`, and `ClearStack`.
- Fires `OnPageChanged` when the top page changes.
- `UIPage`
- Base class for pages with overridable transition hooks.
- Implements `TransitionIn`, `TransitionOut`, and `OnBackPressed`.
- Comes with start/complete events for both in/out transitions.
Stack behavior in short:
- `PushPage(page)` hides the current page (transition out), shows the new page (transition in), and puts it on top.
- `PopPage()` hides the current page (transition out), reveals the previous top page (transition in).
## Quick Start
### 1) Showing a page
```csharp
// Assuming you have a reference to a concrete UIPage (via scene object or instantiated prefab)
[SerializeField] private UIPage albumViewPage;
void OpenAlbum()
{
UIPageController.Instance.PushPage(albumViewPage);
}
```
### 2) Going back
```csharp
void Back()
{
UIPageController.Instance.PopPage();
}
```
### 3) Custom page with simple transitions
```csharp
using System;
using UnityEngine;
public class FadePage : UIPage
{
[SerializeField] private CanvasGroup canvasGroup;
protected override void DoTransitionIn(Action onComplete)
{
// Example: simple fade in (pseudo-code; replace with your tween/anim system)
canvasGroup.alpha = 0f;
gameObject.SetActive(true);
// Tween to alpha 1 over transitionDuration, then:
onComplete?.Invoke();
}
protected override void DoTransitionOut(Action onComplete)
{
// Example: simple fade out
// Tween to alpha 0 over transitionDuration, then:
onComplete?.Invoke();
// The base class will SetActive(false) after completion.
}
}
```
### 4) Wiring a generic Cancel/Back input (optional)
`UIPageController` has placeholders to wire a Cancel action from the Input System. If you want a global back action:
```csharp
// In your bootstrap or scene initializer
var controller = UIPageController.Instance; // ensure it exists in the scene
// Optionally hook up your own input and call:
if (controller.CurrentPage != null)
{
controller.CurrentPage.OnBackPressed();
}
```
## Transitions and Events
`UIPage` exposes these events:
- `OnTransitionInStarted`
- `OnTransitionInCompleted`
- `OnTransitionOutStarted`
- `OnTransitionOutCompleted`
Use them to coordinate animation, audio, or deferred loading.
Example: enable input only after a page is visible.
```csharp
void OnEnable()
{
albumViewPage.OnTransitionInCompleted += EnableAlbumInput;
albumViewPage.OnTransitionOutStarted += DisableAlbumInput;
}
void OnDisable()
{
albumViewPage.OnTransitionInCompleted -= EnableAlbumInput;
albumViewPage.OnTransitionOutStarted -= DisableAlbumInput;
}
```
## Card System Case Studies
These examples show how the card UI uses the page stack.
### Open the Card Menu from gameplay HUD
```csharp
[SerializeField] private UIPage cardMenuPage;
public void OnBackpackButton()
{
UIPageController.Instance.PushPage(cardMenuPage);
}
```
### Navigate from Card Menu to Album view
```csharp
[SerializeField] private UIPage albumViewPage;
public void OnAlbumButton()
{
UIPageController.Instance.PushPage(albumViewPage);
}
```
### Enter Booster Opening flow and then return
```csharp
[SerializeField] private UIPage boosterOpeningPage;
public void OnOpenBooster()
{
// Assume booster count was verified via `CardSystemManager`
UIPageController.Instance.PushPage(boosterOpeningPage);
}
// Inside the booster opening page, when user taps Back or after completion
public override void OnBackPressed()
{
if (!_isTransitioning)
{
// Optional: guard against leaving mid-reveal
// if (!revealComplete) return;
UIPageController.Instance.PopPage();
}
}
```
### Close all card UI and return to HUD
```csharp
public void CloseAllCardUI()
{
UIPageController.Instance.ClearStack();
}
```
## Best Practices
- One active `UIPageController` per UI context (usually one in the main UI scene). Avoid multiple competing controllers.
- Keep transitions short and responsive; the base class already handles `SetActive` lifecycle for you.
- Always check `_isTransitioning` (available in `UIPage`) before triggering back/forward actions to avoid double navigations.
- Use `OnPageChanged` on `UIPageController` to manage global state (e.g., pause input when a modal page is shown).
- If you instantiate pages at runtime, ensure their `GameObject` is inactive by default and let `TransitionIn` activate them.
## API Reference (Essentials)
From `UIPageController`:
- `UIPage CurrentPage` — top of the stack or `null`.
- `event Action<UIPage> OnPageChanged` — fired after a push/pop resolves.
- `void PushPage(UIPage page)` — transitions out current (if any), transitions in the new page, pushes it on the stack.
- `void PopPage()` — transitions out current, reveals previous page with a transition in.
- `void ClearStack()` — transitions out current and empties the stack.
From `UIPage`:
- `string PageName` — a designer-friendly name for logs/diagnostics.
- `float transitionDuration` (protected) — your animations can use this.
- `virtual void TransitionIn()` / `TransitionOut()` — call the overridable `DoTransitionIn`/`DoTransitionOut`.
- `virtual void OnBackPressed()` — default pops the page (calls `UIPageController.Instance.PopPage()`). Override to customize.
- Events: `OnTransitionInStarted`, `OnTransitionInCompleted`, `OnTransitionOutStarted`, `OnTransitionOutCompleted`.
For additional context and examples, see `docs/card_system_playbook.md` and `docs/card_system_integration_and_testing.md`.