Asynchronous screen transition/navigation for Unity.
NavStack is a library for managing screen transitions in Unity. It provides a foundation interface for asynchronous API-based screen transitions, as well as support for integration with uGUI and content management using Resources/Addressables.
Note
NavStack is currently released as a preview version. Feedback through issues or pull requests would be appreciated.
- Unity 2021.3 or later
- UniTask 2.0.0 or later
- Open the Package Manager from Window > Package Manager.
- Click the "+" button > Add package from git URL.
- Enter the following URL:
https://github.com/AnnulusGames/NavStack.git?path=src/NavStack/Assets/NavStack
Alternatively, open Packages/manifest.json and add the following to the dependencies block:
{
"dependencies": {
"com.annulusgames.navstack": "https://github.com/AnnulusGames/NavStack.git?path=src/NavStack/Assets/NavStack"
}
}In NavStack, a screen is divided into units called "Pages." The only requirement for a Page is the implementation of the IPage interface, allowing any object such as GameObjects, VisualElements, or Scenes to be represented as a Page.
Screen transitions and lifecycle management are handled by "Navigation." NavStack provides two types of Navigation: INavigationStack, which can stack Page transitions, and INaviagtionSheet, which switches between active Pages without keeping a history of transitions.
The IPage interface defines the basic events for a Page's lifecycle. Each event is called from the Navigation side, allowing customization of screen transition processes.
publicinterfaceIPage{UniTaskOnNavigatedFrom(NavigationContextcontext,CancellationTokencancellationToken=default);UniTaskOnNavigatedTo(NavigationContextcontext,CancellationTokencancellationToken=default);}| Event | Description |
|---|---|
| OnNavigatedFrom | Called when navigating away from the Page. |
| OnNavigatedTo | Called when navigating to the Page. |
Additionally, by implementing IPageLifecycleEvent, you can add additional lifecycle events for the Page.
publicinterfaceIPageLifecycleEvent{UniTaskOnAttached(CancellationTokencancellationToken=default);UniTaskOnDetached(CancellationTokencancellationToken=default);}NavigationStack supports stacked screen transitions. Pages pushed onto the stack are stacked, and the last pushed Page becomes the active Page. You can push a Page using PushAsync() and pop using PopAsync().
INavigationStacknavigationStack;IPagepage;awaitnavigationStack.PushAsync(page);awaitnavigationStack.PopAsync();You can also add NavigationStack-specific events to Pages by implementing IPageStackEvent.
publicinterfaceIPageStackEvent{UniTaskOnPush(NavigationContextcontext,CancellationTokencancellationToken=default);UniTaskOnPop(NavigationContextcontext,CancellationTokencancellationToken=default);}NavigationSheet supports switching between active Pages, similar to tabs. Unlike NavigationStack, it does not keep a history of Page transitions.
You need to use AddAsync() to add Pages to the NavigationSheet.
INavigationSheetnavigationSheet;IPagepage1;IPagepage2;IPagepage3;awaitnavigationSheet.AddAsync(page1);awaitnavigationSheet.AddAsync(page2);awaitnavigationSheet.AddAsync(page3);To switch the displayed Page, use ShowAsync(). To hide a Page, use HideAsync().
intindex=0;awaitnavigationSheet.ShowAsync(index);awaitnavigationSheet.HideAsync();You can remove Pages using RemoveAsync() or RemoveAllAsync().
awaitnavigationSheet.RemoveAsync(page3);awaitnavigationSheet.RemoveAllAsync();You can pass NavigationContext during Page transitions to pass data between Pages and specify transition options.
You can pass data to the destination Page through NavigationContext.
varpage=newExamplePage();varcontext=newNavigationContext(){Parameters={{"id","123456"}}};awaitnavigationStack.PushAsync(page,context,cancellationToken);classExamplePage:IPage{publicUniTaskOnNavigatedTo(NavigationContextcontext,CancellationTokencancellationToken=default){varid=(string)context.Parameters["id"];
...}
...}You can specify transition options using NavigationOptions.
varcontext=newNavigationContext(){Options=newNavigationOptions(){Animated=true,AwaitOperation=NavigationAwaitOperation.Drop,}};awaitnavigationStack.PushAsync(page,context,cancellationToken);| Property | Description |
|---|---|
| Animated | Specifies whether to play transition animations (default is true). |
| AwaitOperation | Specifies the behavior when a transition operation is called again during Page transition (default is NavigationAwaitOperation.Error). |
When using NavStack with uGUI, add the Navigation Stack / Navigation Sheet component to any object placed under the Canvas.
Next, create Pages for displaying UI. Implement a component that inherits from IPage.
publicclassSamplePage1:MonoBehaviour,IPage{[SerializeField]CanvasGroupcanvasGroup;publicasyncUniTaskOnNavigatedTo(NavigationContextcontext,CancellationTokencancellationToken=default){if(!context.Options.Animated){canvasGroup.alpha=1f;return;}// Example implementation using LitMotion for tween animationsawaitLMotion.Create(0f,1f,0.25f).WithEase(Ease.InQuad).BindToCanvasGroupAlpha(canvasGroup).ToUniTask(CancellationTokenSource.CreateLinkedTokenSource(destroyCancellationToken,cancellationToken).Token);}publicasyncUniTaskOnNavigatedFrom(NavigationContextcontext,CancellationTokencancellationToken=default){if(!context.Options.Animated){canvasGroup.alpha=0f;return;}awaitLMotion.Create(1f,0f,0.25f).WithEase(Ease.OutQuad).BindToCanvasGroupAlpha(canvasGroup).ToUniTask(CancellationTokenSource.CreateLinkedTokenSource(destroyCancellationToken,cancellationToken).Token);}}Prefab the created Page objects for convenience. By adding Prefabed Pages using PushNewObjectAsync() or AddNewObjectAsync(), you can manage object generation/destruction based on the Page lifecycle.
Pageprefab;NavigationStacknavigationStack;NavigationSheetnavigationSheet;awaitnavigationStack.PushNewObjectAsync(prefab);awaitnavigationSheet.AddNewObjectAsync(prefab);TODO
TODO
TODO