| name | app-ui-navigation |
| description | Expert for App UI navigation system - NavGraph, NavHost, NavController, destinations, and visual controllers (AppBar, Drawer, BottomNavBar). Use this skill whenever the user wants to add screens or pages to their Unity app, create a navigation graph, set up a bottom tab bar, implement a side drawer or hamburger menu, add an app bar or toolbar, navigate between views, pass data between screens, manage back stack behavior, create a multi-screen flow (onboarding, login, settings), or implement any kind of screen-to-screen navigation in App UI. Also trigger when the user mentions NavigationScreen, NavigationRail, NavAction, or asks about deep linking or nested navigation. |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep |
App UI Navigation Expert
Expert assistant for implementing navigation systems in Unity using the App UI framework. Specializes in NavGraph construction, NavHost setup, NavController usage, and visual navigation component control.
Core Concepts
Navigation System Architecture
The App UI navigation system consists of these key components:
- NavGraphViewAsset - The main resource that contains navigation graphs
- NavGraph - A set of pages that can be navigated between
- NavDestination - A page in the navigation graph
- NavAction - An action that navigates from one destination to another
- NavHost - A component that hosts and displays a navigation graph
- NavController - Controls navigation and back stack management
- INavVisualController - Controls visual navigation components (AppBar, Drawer, etc.)
Key Design Principles
- Start Destination Required - Every NavGraph must have exactly one start destination
- Back Stack Managed - NavController automatically manages the back stack
- Visual Component Control - AppBar, Drawer, BottomNavBar, and NavigationRail are controlled via INavVisualController
- Nested Graphs Supported - Create complex flows with nested navigation graphs
- Global Actions - Actions without a source destination are global and available from any destination
- Local Actions - Actions with a source destination are only available from that destination
- Code Generation - Generate strongly-typed constants for destinations and actions
Essential Patterns
1. Never Forget the Start Destination
A NavGraph MUST have a start destination. This is the first page shown:
navGraph.startDestination = homeDestination;
2. Always Implement INavVisualController
Control navigation UI components through a single controller:
class MyNavVisualController : INavVisualController
{
public void SetupAppBar(AppBar appBar, NavDestination destination, NavController navController)
{
appBar.title = destination.label;
}
public void SetupDrawer(Drawer drawer, NavDestination destination, NavController navController)
{
}
public void SetupBottomNavBar(BottomNavBar bottomNavBar, NavDestination destination, NavController navController)
{
}
public void SetupNavigationRail(NavigationRail navigationRail, NavDestination destination, NavController navController)
{
}
}
3. Distinguish Global vs Local Actions
Global actions work from any destination, local actions only from specific sources:
var logoutAction = new NavAction { actionId = "logout", destination = loginGraph.startDestination };
navGraph.globalActions.Add(logoutAction);
var settingsAction = new NavAction { actionId = "openSettings", source = homeDestination, destination = settingsDestination };
navGraph.actions.Add(settingsAction);
4. Use DefaultDestinationTemplate for Standard Screens
The DefaultDestinationTemplate handles NavigationScreen instantiation and visual component setup:
var destination = new NavDestination
{
label = "Home",
name = "home",
template = new DefaultDestinationTemplate
{
screenType = typeof(HomeScreen),
showAppBar = true,
showDrawer = true,
showBottomNavBar = true
}
};
5. Properly Handle Arguments
Pass data to destinations using the Argument array:
navController.Navigate("details", new[] {
new Argument { key = "id", value = 123 }
});
public class DetailsScreen : NavigationScreen
{
public override void OnEnter(NavController controller, NavDestination destination, Argument[] args)
{
var id = args.First(a => a.key == "id").value;
}
}
6. Manage Back Stack Correctly
Control back stack behavior through NavAction properties:
var action = new NavAction
{
actionId = "navigateToHome",
destination = homeDestination,
backStackBehavior = BackStackBehavior.ClearStack
};
Common Patterns
App Bar Setup
public void SetupAppBar(AppBar appBar, NavDestination destination, NavController navController)
{
appBar.title = destination.label;
var editButton = new ActionButton { icon = "edit", label = "Edit" };
editButton.clickable.clicked += () => navController.Navigate("editScreen");
appBar.Add(editButton);
}
Drawer Setup
public void SetupDrawer(Drawer drawer, NavDestination destination, NavController navController)
{
drawer.Add(new DrawerHeader { title = "Navigation" });
drawer.Add(new Divider { vertical = false });
var homeItem = new MenuItem { icon = "home", label = "Home", selectable = true };
homeItem.SetValueWithoutNotify(destination.name == "home");
homeItem.clickable.clicked += () => navController.Navigate("home");
drawer.Add(homeItem);
var settingsItem = new MenuItem { icon = "settings", label = "Settings", selectable = true };
settingsItem.SetValueWithoutNotify(destination.name == "settings");
settingsItem.clickable.clicked += () => navController.Navigate("settings");
drawer.Add(settingsItem);
}
BottomNavBar Setup
public void SetupBottomNavBar(BottomNavBar bottomNavBar, NavDestination destination, NavController navController)
{
var homeItem = new BottomNavBarItem("home", "Home", () => navController.Navigate("home"))
{
isSelected = destination.name == "home"
};
bottomNavBar.Add(homeItem);
var exploreItem = new BottomNavBarItem("explore", "Explore", () => navController.Navigate("explore"))
{
isSelected = destination.name == "explore"
};
bottomNavBar.Add(exploreItem);
}
NavigationRail Setup
public void SetupNavigationRail(NavigationRail navigationRail, NavDestination destination, NavController navController)
{
navigationRail.anchor = NavigationRailAnchor.Start;
navigationRail.labelType = LabelType.Selected;
var homeItem = new NavigationRailItem { icon = "home", label = "Home", selected = destination.name == "home" };
homeItem.clickable.clicked += () => navController.Navigate("home");
navigationRail.mainContainer.Add(homeItem);
var settingsItem = new NavigationRailItem { icon = "settings", label = "Settings", selected = destination.name == "settings" };
settingsItem.clickable.clicked += () => navController.Navigate("settings");
navigationRail.mainContainer.Add(settingsItem);
}
Per-Screen Visual Setup
public class HomeScreen : NavigationScreen
{
protected override void SetupAppBar(AppBar appBar, NavController navController)
{
appBar.title = "Home";
var menuButton = new ActionButton { icon = "menu", label = "Menu" };
menuButton.clickable.clicked += () => navController.Navigate("settings");
appBar.Add(menuButton);
}
}
Nested Navigation Graphs
var mainGraph = new NavGraph { name = "main", startDestination = homeDestination };
mainGraph.destinations.Add(homeDestination);
var settingsGraph = new NavGraph { name = "settings", startDestination = settingsHomeDestination };
settingsGraph.destinations.Add(settingsHomeDestination);
navController.Navigate("settings");
Important Patterns to Avoid
- Don't forget to set start destination - Every graph must have one
- Don't mix global and local action logic - Keep them separate
- Don't modify destination.label at runtime - It won't affect AppBar title, use the visual controller
- Don't assume OnEnter/OnExit are called multiple times - They're called per navigation
- Don't navigate without a valid NavController reference - Ensure it's properly initialized
Integration with App Builder
public class MyAppBuilder : UIToolkitAppBuilder<MyApp>
{
protected override void OnConfiguringApp(AppBuilder builder)
{
base.OnConfiguringApp(builder);
var navGraphAsset = Resources.Load<NavGraphViewAsset>("Navigation/MyNavGraph");
builder.services.AddSingleton(navGraphAsset);
}
protected override void OnAppReady(MyApp app)
{
base.OnAppReady(app);
var navHost = new NavHost();
navHost.visualController = new MyNavVisualController();
var navGraphAsset = app.GetService<NavGraphViewAsset>();
navHost.LoadGraph(navGraphAsset);
root.Add(navHost);
}
}
Code Generation Best Practices
Use the Navigation Graph Editor's code generator to create strongly-typed constants:
public partial static class Actions
{
public const string NavigateToHome = "navigateToHome";
public const string NavigateToSettings = "navigateToSettings";
}
public partial class Destinations
{
public const string Home = "home";
public const string Settings = "settings";
}
navController.Navigate(Destinations.Home);
File Locations
- Navigation Graph Assets:
Assets/Resources/Navigation/
- Navigation Screens:
Assets/Scripts/Navigation/Screens/
- Visual Controllers:
Assets/Scripts/Navigation/Controllers/
- Generated Code:
Assets/Scripts/Navigation/Generated/ (created by code generator)
Reference Documentation
Consult reference.md when you need exact API signatures for NavGraph, NavDestination, NavAction, NavController, or NavHost, full property lists, lifecycle event details, or advanced patterns like nested graph resolution and custom destination templates. See examples/ for complete working code samples.