6.3 KiB
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.csAssets/Scripts/UI/Core/UIPage.cs
Table of Contents
- Concepts
- Quick Start
- Transitions and Events
- Card System Case Studies
- Best Practices
- API Reference (Essentials)
Concepts
UIPageController- A singleton navigator that maintains a stack of
UIPageinstances. - Provides
PushPage,PopPage, andClearStack. - Fires
OnPageChangedwhen the top page changes.
- A singleton navigator that maintains a stack of
UIPage- Base class for pages with overridable transition hooks.
- Implements
TransitionIn,TransitionOut, andOnBackPressed. - 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
// 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
void Back()
{
UIPageController.Instance.PopPage();
}
3) Custom page with simple transitions
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:
// 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:
OnTransitionInStartedOnTransitionInCompletedOnTransitionOutStartedOnTransitionOutCompleted
Use them to coordinate animation, audio, or deferred loading.
Example: enable input only after a page is visible.
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
[SerializeField] private UIPage cardMenuPage;
public void OnBackpackButton()
{
UIPageController.Instance.PushPage(cardMenuPage);
}
Navigate from Card Menu to Album view
[SerializeField] private UIPage albumViewPage;
public void OnAlbumButton()
{
UIPageController.Instance.PushPage(albumViewPage);
}
Enter Booster Opening flow and then return
[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
public void CloseAllCardUI()
{
UIPageController.Instance.ClearStack();
}
Best Practices
- One active
UIPageControllerper UI context (usually one in the main UI scene). Avoid multiple competing controllers. - Keep transitions short and responsive; the base class already handles
SetActivelifecycle for you. - Always check
_isTransitioning(available inUIPage) before triggering back/forward actions to avoid double navigations. - Use
OnPageChangedonUIPageControllerto manage global state (e.g., pause input when a modal page is shown). - If you instantiate pages at runtime, ensure their
GameObjectis inactive by default and letTransitionInactivate them.
API Reference (Essentials)
From UIPageController:
UIPage CurrentPage— top of the stack ornull.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 overridableDoTransitionIn/DoTransitionOut.virtual void OnBackPressed()— default pops the page (callsUIPageController.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.