StackUI

April 29, 2026 · View on GitHub

轻量、直观、可落地的 Unity 栈式 UI 框架。
用最少代码完成页面导航、弹窗叠加、生命周期管理与资源缓存控制。


主要功能

核心能力说明核心 API
栈式导航提供栈式的页面打开、后退等导航功能Navigation.Push / Navigation.Pop / Navigation.CanPop 等系列方法
页面参数页面切换时支持传递上下文参数Navigation.Push / Navigation.Pop 等系列方法
历史裁剪栈式链路中根据条件把某一段页面路径去除Navigation.PushAndRemoveAll / Navigation.PushAndRemoveUntil / Navigation.PopUntil /Navigation.Clear
弹窗管理弹窗叠加显示在页面上Navigation.ShowWin / Navigation.HideWin / Navigation.ExistWin / Navigation.GetWin
生命周期可重写弹窗和页面全生命周期Presenter.OnAssetLoaded Presenter.OnInit / Presenter.OnReInit / Presenter.OnClose / Presenter.OnDispose
资源策略可单独控制某个页面具体使用资源和缓存策略Navigation.SetDontDestroyAsset / Navigation.SetAssetName
事件管理自动回收UI事件Presenter.ListenUnity
UI模板自定义UI风格 方便编辑器里直接创建

框架设计

  • Navigation 负责页面 窗口管理,提供了控制页面和获取状态的方法
  • Presenter 负责业务逻辑 ,由用户继承
  • View 负责界面显示,由用户继承

生命周期(Presenter)

回调触发时机常见用途
OnAssetLoaded()资源首次加载或重载后初始化一次性资源
OnInit(object arg)界面从关闭 -> 打开绑定事件、根据参数初始化界面
OnReInit(object arg)已打开状态下再次打开刷新数据、局部重绘
OnClose()界面关闭(隐藏/销毁前)停止逻辑
OnDispose()资源销毁前(仅销毁路径)清理资源

安装方式

下载项目整个拷贝到项目Assets根路径下,或者使用推荐方式:

使用包管理器 Install package from git URL,填入 https://github.com/Eashiong/StackUI

导入示例

里面提供了一些使用例子,请查看。如果是下载项目导到到工程的 请把Demo~ 文件改名为Demo 即就会把示例自动导入到工程中

如果是使用使用包管理器安装的,可以直接从包管理器安装示例


快速开始

1)注册页面

using StackUI;
using UnityEngine;

public class AppEntry : MonoBehaviour
{
    void Start()
    {
        Navigation.AddTable<LoginPresenter>("UI/LoginView");
        Navigation.AddTable<HomePresenter>("UI/HomeView");
        Navigation.Push<LoginPresenter>();
    }
}

2)定义 View

using StackUI;

public class LoginView : View
{
    public UIButton loginBtn;
}

3)定义 Presenter

using StackUI;

public class LoginPresenter : Presenter<LoginView>
{
    public override void OnInit(object arg)
    {
        ListenUnity(view.loginBtn.onClick, OnLoginClick);
    }

    private void OnLoginClick()
    {
        Navigation.PopAndPush<HomePresenter>("from login");
    }
}

特殊场景举例

业务场景推荐 API说明
登录成功后进入主页,后续后退时候不需要返回登录页PopAndPush把主页与登录页进行置换
支付完成后回到主线并清理支付流程页PushAndRemoveUntil可以跳过支付中间的一系列页面直接回到主线
连续返回直到登录页PopUntil / Clear + Push强制退出登录
节日活动换皮SetAssetName可下次刷新或立即刷新页面皮肤

资源加载与缓存策略

默认行为

  • 默认加载器:Resources.Load + Instantiate
  • 默认缓存:dontDestroy = true(关闭后隐藏,不销毁)

注册时指定策略

Navigation.AddTable<HomePresenter>("UI/HomeView", dontDestroy: false,CustomAssetRemoveHandler);

注册时使用自定义 Loader

Navigation.AddTable<HomePresenter>(
    "UI/HomeView",
    dontDestroy: true,
    loader: CustomLoader,
    AssetRemoveHandler
);

private GameObject CustomLoader(string sourceName)
{
    //比如从本地读取
    //return GameObject.Instantiate(Resources.Load<GameObject>(sourceName));
    //比如从AB包
    //var assetBundle = AssetBundle.LoadFromFile(abfilePath);
    //return assetBundle.LoadAsset<GameObject>(sourceName);

    //这里返回一个空物体
    return new GameObject(sourceName).AddComponent<AssetLoaderView>().gameObject;
}
private void CustomAssetRemoveHandler(AssetRemoveHandlerArgs args)
{
    Debug.Log($"自定义资源清理逻辑: id:{args.id}, viewName:{args.viewName}, asset:{args.asset} 被删除");

    //比如清理AB包
    //assetBundle.Unload(false);

    UnityEngine.GameObject.Destroy(args.asset);
}

运行时换肤

Navigation.SetAssetName<HomePresenter>("UI/HomeView_Festival");//下次打开界面时会自动生效
//如果想立即生效 使用置换API
if(Navigation.IsCurrent<HomePresenter>())
{
    Navigation.PopAndPush<HomePresenter>();
}

常用查询接口

var current = Navigation.CurrentInstance();
var currentId = Navigation.CurrentInstanceID();
bool isHome = Navigation.IsCurrent<HomePresenter>();
bool canBack = Navigation.CanPop();

bool hasBagWin = Navigation.ExistWin<BagWinPresenter>();
var bagWin = Navigation.GetWin<BagWinPresenter>();

string asset = Navigation.GetAssetName<HomePresenter>();

编辑器工具

UI模板

  • 支持右键创建模板UI
image
  • 自定义模板

在Assets面板右键创建一个 Setting Data资源 按需配置prefab

image

然后配置到Project Setting/StackUI 生效

image