跳转到内容

10. 运行示例(Samples~)

该包在 Samples~/ 下提供 7 个独立示例。界面控件全部使用标准 Unity UI Toolkit 控件(ButtonLabelTextFieldToggleScrollView)——不需要任何下游 UI 包。

前置条件

  • 项目中已安装 sus-router + sus-core
  • 已导入 UPM Samples:Window → Package Manager → SusRouter → Samples → Import
  • 场景中有 UIDocument(需要 EventSystem)
  • 每个示例都带有 [RequireComponent(typeof(UIDocument))]

场景搭建

  1. 创建 GameObject → Add Component → UIDocument
  2. Add Component → 示例脚本(例如 BasicRoutingExample
  3. GameObject → UI → Event System(如果缺少的话)
  4. Play

总览

#示例路由器特性
1BasicRoutingPush、Replace、Back、Home、CurrentRoute
2KeepAliveKeepAlive=true/false、缓存
3GuardsBeforeEach、CanEnter、BeforeResolve、重定向
4Modals+TransitionsSusRouterModal(InfoDialog、ConfirmDialog)、Fade/Slide、NavigateWithTransition
5Nested+Namedchildren、PushNamed、:id、?q=、alias、redirect、lazy
6RouteLinkSusRouteLink、Bind(router)、router-link-active/exact-active
7FullDemo全部功能:KeepAlive、守卫、模态框、过渡动画、嵌套、命名路由、主题

示例 1:BasicRouting

脚本: BasicRoutingExample.cs

演示基础导航:Push、Replace、Back、Home、显示 CurrentRoute。

导航 —— UITK 标签栏

4 个标签 Button:Home、About、Contact、Settings。每个标签会 Push 对应的路径。

屏幕

  • HomeScreen —— 欢迎语 + 导航按钮 + 路由标签(Label
  • AboutScreen —— 说明文字 + 指向 Home 的 SusRouteLink + 图片占位符
  • ContactScreen —— 若干 TextField + 提交 Button
  • SettingsScreen —— 若干 Toggle

操作按钮

  • Back —— UITK Button,驱动导航
  • 当前路由以标签 Label 的形式显示

关键代码

csharp
// tab bar navigation
void OnTabChanged(string path)
{
    Router.Push(path);
}

// SusRouteLink
var link = new SusRouteLink { To = "/about", Exact = true };
link.Bind(Router); // enables router-link-active

示例 2:KeepAlive

脚本: KeepAliveExample.cs

展示 KeepAlive=true(状态保留)与 false(重新创建)之间的区别。

导航 —— UITK 标签栏

3 个标签:Counter [K]、Form [K]、Settings。[K] 表示 KeepAlive=true。

屏幕

  • CounterScreen(KeepAlive) —— 计数器 + Button +/−。离开再返回后计数依然保留。
  • FormScreen(KeepAlive) —— 若干 TextField。切换标签后输入的文本依然保留。
  • SettingsScreen(非 KeepAlive) —— 若干 Toggle;每次都会重新创建。

关键代码

csharp
Router.Register("/counter", typeof(CounterScreen),
    new SusRouteConfig { KeepAlive = true });
Router.Register("/settings", typeof(SettingsScreen)); // KeepAlive=false

示例 3:Guards

脚本: GuardsExample.cs

演示守卫(guard)流水线。

导航 —— UITK 标签栏

4 个标签:Home、Admin、Profile、OldAdmin。通过 Toggle「Logged in」控制登录状态。

守卫

  • BeforeEach —— 未登录时拦截除 home 以外的所有路由
  • AdminGuard —— 当管理表单存在未保存修改时,触发 ISusRouteGuard.CanLeave
  • Redirect —— 通过 SusRouteConfig.Redirect/old-admin/admin

屏幕

  • HomeScreen —— 说明文字 + 试用按钮
  • AdminScreen —— TextField 表单 + 未保存修改时的 CanLeave 确认弹层
  • ProfileScreen —— 仅在已登录时可用

关键代码

csharp
Router.BeforeEach((from, to) =>
{
    if (to.FullPath == "/home") return true;
    if (!_isLoggedIn) return false; // block
    return true;
});

Router.Register("/admin", typeof(AdminScreen), new SusRouteConfig
{
    Guard = new AdminGuard()
});

示例 4:Modals & Transitions

脚本: ModalExample.cs

演示 SusRouterModal、模态框服务与过渡动画。

导航 —— UITK 标签栏

3 个标签:Page 1–3。可通过 NavigateWithTransition 附带 Fade 动画导航(可选 Toggle)。

模态框

  • InfoDialog —— 信息提示 + Close Button
  • ConfirmDialog —— 带 OK/Cancel Button 的确认框

操作按钮

  • Open Info / Open Confirm / Stack 3
  • Close Top —— ModalService.Close()

关键代码

csharp
// Show modal
Router.ModalService.Show(typeof(InfoDialog), new() {
    ["title"] = "Information",
    ["message"] = "Welcome!"
});

// Navigate with animation
Router.NavigateWithTransition("/page-2", 0.3f);

示例 5:嵌套路由与命名路由

脚本: AdvancedRoutingExample.cs

演示命名路由、嵌套路由、别名、重定向、查询参数与延迟加载。

导航 —— UITK 标签栏

5 个标签:Main Menu(别名)、Battle(:id)、Settings(嵌套)、Search(?q=)、Lazy。

能力

  • 命名路由 —— /battle/:id,配合 pathParams 使用 PushNamed
  • 别名 —— /menu/main-menu
  • 重定向 —— /old-menu/main-menu
  • 嵌套 —— /settings/profile/settings/privacy(SettingsScreen 内部的标签栏)
  • 查询参数 —— /search?q=hello&page=1
  • 延迟加载 —— /lazy,LazyFactory

关键代码

csharp
Router.Register("/battle/:id", typeof(BattleScreen), new SusRouteConfig
{
    Name = "battle",
    Transition = SusRouteTransition.SlideLeft()
});

Router.PushNamed("battle", new() { ["id"] = "42" });

// Nested routes
Router.Register("/settings", typeof(SettingsScreen), new SusRouteConfig
{
    Children = new List<SusRouteRecord>
    {
        new SusRouteRecord("profile", typeof(LabelScreen)),
        new SusRouteRecord("privacy", typeof(LabelScreen)),
    }
});

脚本: RouteLinkExample.cs

演示带自动高亮功能的 SusRouteLink。

屏幕上有三个 SusRouteLink 实例:Home、Battle、Settings。每个都会自动获得 router-link-active / router-link-exact-active 类。

关键代码

csharp
var homeLink = new SusRouteLink { To = "/home", Exact = true };
homeLink.Bind(Router); // auto-highlight

var battleLink = new SusRouteLink { To = "/battle/42" };
battleLink.Bind(Router);

精确匹配同样可用:

csharp
var exactLink = new SusRouteLink { To = "/home", Exact = true };
// router-link-exact-active only on exact /home

示例 7:完整演示

脚本: FullDemoExample.cs

综合示例,结合了所有路由器功能与主题化。

布局 —— 侧边栏 + 内容区

  • 侧边栏 —— 纵向 UITK 标签 Button:Dashboard、Users、Settings、About
  • 内容区 —— ScrollView + 挂载的路由宿主

特性

  • KeepAlive:Dashboard / Users
  • 守卫:嵌套 :id 上的 UserDetailGuard
  • 模态框:「Open Modal」→ AboutDialog(SusRouterModal
  • 过渡动画:屏幕之间的 Fade
  • 嵌套:/users/:id
  • 命名路由:users / user-detail
  • 主题:Toggle Dark + SusThemeService

关键代码

csharp
// Sidebar — vertical tab buttons push routes
navTabs.OnChanged += path => Router.Push(path);

// Modal
Router.ModalService.Show(typeof(AboutDialog), new() {
    ["title"] = "About",
    ["message"] = "SusRouter Full Demo"
});

故障排查

现象原因解决办法
什么都不显示UIDocument 没有 PanelSettings分配 PanelSettings,或让示例从 Resources 加载
标签按钮没有反应OnChanged 未接线在事件处理器中绑定 Router.Push
按钮点击无效场景中没有 EventSystem向场景添加 Event System
找不到 PushNamed 对应的路由SusRouteConfig 中没有 Name设置 Name = "..."
KeepAlive 不缓存KeepAlive 未设为 true设置 KeepAlive = true
router-link-active 缺失SusRouteLink 没有调用 Bind调用 link.Bind(router)
模态框不显示没有 OverlayHostrouter.Init(overlayHost)
重定向死循环Redirect 指向自身检查重定向链