MyFramework 用法说明(三):创建并打开第一个热更界面 📅 2026/7/10 9:56:43 前两篇已经完成了框架初始化并说明了GameEntry - Game - LaunchScene - GameHotFix - MainScene的启动流程。这一篇开始进入实际开发创建一个最简单的热更 UI并在MainSceneLoading中打开它。一、这一篇的目标本篇要完成的效果很简单进入MainScene后自动打开一个主界面UIMain。流程如下GameHotFix ↓ MainScene ↓ MainSceneLoading ↓ LOADUIMain() ↓ 显示主界面建议项目业务 UI 优先放在热更层也就是Assets/Scripts/HotFix/UI这样后续界面逻辑修改后可以通过热更新更新。二、创建 UI 脚本先创建一个最简单的UIMain。路径建议Assets/Scripts/HotFix/UI/UIMain.cs示例代码public class UIMain : LayoutScript { protected myUGUIText mTitleText; // 标题文本 protected LegendButton mCloseButton; // 关闭按钮 public override void assignWindow(myUIObject parent, string name) { base.assignWindow(parent, name); newObject(out mTitleText, TitleText); newObject(out mCloseButton, CloseButton); } public override void init() { base.init(); mCloseButton.registeCollider(onCloseButtonClick); } protected override void onGameState() { base.onGameState(); mTitleText.setText(Hello MyFramework); } protected void onCloseButtonClick() { close(); } }这里先手写一版方便理解 UI 脚本结构。实际项目中mTitleText、mCloseButton、assignWindow、按钮注册等代码通常可以通过 UI 代码生成器生成不需要每个界面都手写。三、准备 UI Prefab创建一个 UI Prefab例如UIMain ├── TitleText └── CloseButton节点名需要和脚本中的绑定名一致newObject(out mTitleText, TitleText); newObject(out mCloseButton, CloseButton);如果节点名写错运行时就找不到对应对象。所以实际项目里更推荐使用 UI 生成器从 Prefab 反向生成脚本减少手写字符串错误。在UIMain节点上挂一个UGUIGenerator,然后填写相关信息,添加需要生成变量的节点,然后点击生成代码即可.四、注册 UI热更 UI 的注册入口在Assets/Scripts/HotFix/UI/LayoutRegisterHotFix.cs示例public class LayoutRegisterHotFix { public static UIMain mUIMain; // 主界面 public static void registeAll() { // auto generate start registeLayoutUIMain((script) { mUIMain script; }); // auto generate end } }registeLayoutUIMain的作用是告诉LayoutManager这个界面存在。这个界面对应哪个脚本类型。界面加载后需要把实例保存到哪里。后续就可以通过LOADUIMain(); SHOWUIMain(); HIDEUIMain(); UNLOADUIMain();来管理这个界面。这些函数在LT类中,可以在文件开头写上using static LT;或者调用时写LT.LOADUIMain()也可以.五、在 MainSceneLoading 中打开 UI主业务入口在Assets/Scripts/HotFix/GameScene/MainScene/MainSceneLoading.cs修改onInitpublic class MainSceneLoading : SceneProcedure { protected override void onInit(SceneProcedure lastProcedure) { base.onInit(lastProcedure); LOADUIMain(); } protected override void onExit(SceneProcedure nextProcedure) { base.onExit(nextProcedure); HIDEUIMain(); } }这样进入MainSceneLoading时就会加载并显示UIMain。离开这个流程时会隐藏UIMain。如果这个 UI 只在当前流程使用并且退出后不再保留也可以在退出时卸载protected override void onExit(SceneProcedure nextProcedure) { base.onExit(nextProcedure); UNLOADUIMain(); }简单理解HIDE适合临时隐藏下次还会继续使用。UNLOAD适合彻底关闭并释放界面实例和资源引用。六、LOAD、SHOW、HIDE、UNLOAD 的区别开发 UI 时不要把所有操作都理解成SetActive。MyFramework 中更推荐按生命周期区分LOADUIMain(); // 加载并显示 SHOWUIMain(); // 已加载时显示 HIDEUIMain(); // 隐藏但不销毁 UNLOADUIMain(); // 卸载并释放常见用法// 第一次打开界面 LOADUIMain(); // 界面已经加载过只是重新显示 SHOWUIMain(); // 暂时隐藏 HIDEUIMain(); // 当前流程结束彻底卸载 UNLOADUIMain();如果一个界面会频繁打开关闭比如背包、角色面板可以优先考虑HIDE。如果一个界面只在某个流程中临时使用比如结算界面、新手引导某一步界面可以在流程退出时UNLOAD。SHOW其实作用并不大,大多数时候都可以直接使用LOAD代替,因为LOAD中会去判断是否已经加载界面了七、UI 逻辑应该放在哪里建议按这个规则拆LayoutScript 负责界面内部逻辑 SceneProcedure 负责什么时候打开或关闭界面 LayoutManager 负责界面生命周期比如UIMain自己负责刷新标题 刷新按钮状态 响应按钮点击 刷新界面显示内容MainSceneLoading负责进入流程时打开 UIMain 退出流程时隐藏或卸载 UIMain不要把所有 UI 打开关闭都堆在一个全局 UIManager 里。MyFramework 更推荐让每个SceneProcedure只关心自己的界面。八、按钮点击后的流程切换如果按钮点击后需要进入另一个流程不建议在 UI 里写太多流程细节。可以在 UI 中只发起一个明确请求protected void onCloseButtonClick() { close(); }如果是进入背包流程可以写成类似protected void onBagButtonClick() { FrameUtility.changeProcedureMainSceneBag(); }更复杂的项目里也可以通过命令或事件转发让 UI 不直接关心具体流程类型。原则是UI 负责交互。流程负责状态切换。业务系统负责数据处理。九、推荐开发顺序实际开发一个新界面时可以按这个顺序1. 创建 UI Prefab 2. 按规则命名节点 3. 使用 UI 生成器生成 LayoutScript 4. 在 LayoutRegisterHotFix 中注册界面 5. 在对应 SceneProcedure 中 LOAD / HIDE / UNLOAD 6. 在 LayoutScript 中补充业务刷新逻辑如果先不使用生成器也可以手写脚本但节点多了以后不推荐长期手写。UI 数量一多手写绑定代码很容易出现节点名写错 按钮忘记注册 数组节点漏绑定 Prefab 改名后脚本没改 重复写大量 assignWindow这些都应该交给生成器处理。十、完整最小示例UIMain.cspublic class UIMain : LayoutScript { protected myUGUIText mTitleText; // 标题文本 protected LegendButton mCloseButton; // 关闭按钮 public override void assignWindow(myUIObject parent, string name) { base.assignWindow(parent, name); newObject(out mTitleText, TitleText); newObject(out mCloseButton, CloseButton); } public override void init() { base.init(); mCloseButton.registeCollider(onCloseButtonClick); } protected override void onGameState() { base.onGameState(); mTitleText.setText(Hello MyFramework); } protected void onCloseButtonClick() { close(); } }LayoutRegisterHotFix.cspublic class LayoutRegisterHotFix { public static UIMain mUIMain; // 主界面 public static void registeAll() { // auto generate start registeLayoutUIMain((script) { mUIMain script; }); // auto generate end } }MainSceneLoading.cspublic class MainSceneLoading : SceneProcedure { protected override void onInit(SceneProcedure lastProcedure) { base.onInit(lastProcedure); LOADUIMain(); } protected override void onExit(SceneProcedure nextProcedure) { base.onExit(nextProcedure); HIDEUIMain(); } }十一、总结这一篇完成了第一个热更 UI 的基本接入。核心步骤只有三个创建LayoutScript。在LayoutRegisterHotFix中注册。在SceneProcedure中打开。MyFramework 的 UI 管理重点不是简单替代SetActive而是把界面放进统一生命周期中加载由LayoutManager管。界面实例由GameLayout管。界面逻辑由LayoutScript管。打开关闭时机由SceneProcedure管。这样后续项目界面变多以后每个界面依然能保持清楚的责任边界。