本篇核心知识点:栈结构弹窗完整交互逻辑、BasePanel 基类虚函数设计、界面打开 / 关闭 / 暂停 / 恢复生命周期、GraphicRaycaster 射线开关、DoTween 动画插件基础(位移 / 缩放 / 跳跃动画)、界面关闭按钮通用封装、面向对象共性抽取、新增界面零改动拓展规范
一、栈结构弹窗完整交互逻辑
1 概念
基于 Stack 栈先进后出规则管理多层弹窗,打开新面板时暂停上一层交互,关闭顶层自动恢复上一层操作,解决多弹窗互相遮挡、底层仍可点击的 Bug,所有界面入栈 / 出栈统一由 UIManager 管控。
2 特性 / 规则
-
Push 入栈:新界面创建完成存入栈,栈顶旧面板暂停交互;
-
Pop 出栈:销毁 / 隐藏当前栈顶面板,栈内下一层恢复交互;
-
栈永远保留主界面,栈长度不会为 0;
-
每层界面通过 GraphicRaycaster 控制射线是否接收点击,暂停时关闭射线。
3 语法 & 代码片段
private Stack<BasePanel> panelStack = new Stack<BasePanel>();
// 入栈打开面板
public void PushPanel(PanelType type){
Base newPanel = CreatePanel(type);
if(panelStack.Count > 0){
// 获取栈顶,暂停交互
BasePanel top = panelStack.Peek();
top.Pause();
}
panelStack.Push(newPanel);
new.Open();
}
// 出栈关闭顶层
public void PopPanel(){
if(panelStack.Count <= 1) return;
BasePanel top = panelStack.Pop();
top.Close();
// 恢复新栈顶交互
panelStack.Peek().Resume();
}
4 相关知识点对比
无栈直接叠加弹窗 VS 栈管理弹窗
无栈:多层弹窗叠加后底层按钮仍能点击,交互错乱;
栈管理:自动暂停下层,仅栈顶可交互,逻辑统一规范。
5 模块拓展
游戏商城、背包详情、活动弹窗多层嵌套场景标准实现。
二、BasePanel 基类虚函数架构设计
1 概念
抽取所有界面共有逻辑封装父类 BasePanel,使用虚函数virtual而非抽象函数,子类按需重写生命周期方法,无需强制实现无关逻辑,面向对象共性抽取核心思想。
2 特性 / 规则
-
四大生命周期虚方法:Open 打开、Close 关闭、Pause 暂停、Resume 恢复;
-
虚函数:子类可重写也可直接使用父类默认逻辑;抽象函数强制全部实现;
-
基类自动缓存 GraphicRaycaster、关闭按钮,子类无需重复查找组件;
-
所有自定义界面脚本全部继承 BasePanel。
3 语法 & 代码片段
using UnityEngine.UI;
public class BasePanel : MonoBehaviour{
protected GraphicRay ray;
protected Button closeBtn;
// 界面打开执行
public virtual void Open(){
gameObject.SetActive(true);
ray = GetComponent<GraphicRaycaster>();
ray.enabled = true;
closeBtn = transform.Find("CloseBtn")?.GetComponent<Button>();
if(closeBtn != null)
closeBtn.onClick.Add(UIManager.Instance.PopPanel);
}
// 界面关闭执行
public virtual void Close(){
ray.enabled = false;
gameObject.SetActive(false);
}
// 暂停交互
public virtual void Pause(){
ray.enabled = false;
}
// 恢复交互
public virtual void Resume(){
ray.enabled = true;
}
}
// 子类重写示例
public class TaskPanel : BasePanel{
public override void Open(){
base.Open();
// 任务界面独有的打开逻辑
}
}
4 相关知识点对比
virtual 虚函数 VS abstract 抽象函数
virtual:可选重写,无对应需求直接复用父类逻辑;
abstract:子类必须全部实现,界面无暂停逻辑也要空方法,冗余。
5 模块拓展
基类可拓展 OnDestroy、数据刷新通用方法,统一所有界面数据更新入口。
三、界面组件自动缓存与关闭按钮封装
1 概念
在 BasePanel 父类 Open 方法中自动查找 GraphicRaycaster 射线组件、层级下关闭按钮,无需每个界面手动拖拽赋值,自动绑定关闭出栈事件,减少重复代码。
2 特性 / 规则
-
Transform.Find 按名称查找按钮,找不到不会报错;
-
按钮存在时自动绑定 UIManager 出栈方法,无按钮跳过绑定;
-
Pause/Resume 直接修改 ray.enabled 开关点击交互,控制界面是否可点击。
3 语法 & 代码片段
// 基类自动查找关闭按钮
closeBtn = transform.Find("CloseBtn")?.GetComponent<Button>();
if(closeBtn != null){
closeBtn.onClick.AddListener(()=>{
UIManager.Instance.PopPanel();
});
}
// 暂停关闭射线,无法点击
ray.enabled = false;
4 相关知识点对比
编辑器拖拽赋值按钮 VS 代码自动查找
拖拽:预制体改动容易丢失引用,多人协作易出错;
代码查找:统一规范,新增界面只需命名 CloseBtn 自动绑定。
5 模块拓展
拓展返回按钮、确认按钮统一查找绑定逻辑。
四、DoTween 补间动画插件基础
1 概念
第三方轻量动画插件,无需动画窗口,代码控制 UI 位移、缩放、跳跃过渡动画,常用于弹窗弹出入场效果,提升界面视觉手感。
2 特性 / 规则
-
核心 API:DOLocalMove 局部位移、DOScale 缩放、DOJump 跳跃;
-
动画执行前可将 UI 移至屏幕外,再缓动滑入;
-
支持自定义动画时长、运动曲线,无需创建 AnimationClip 资源。
3 语法 & 代码片段
using DG.Tweening;
public override void Open(){
base.Open();
// 入场:屏幕左侧滑入
transform.localPosition = new Vector3(3000, transform.localY, transform.localZ);
transform.DOLocalMove(Vector3.zero, 1f);
// 缩放弹出动画
transform.localScale = Vector3.zero;
transform.DOScale(Vector3.one, 0.5f);
// 跳跃入场动画
transform.DOJump(Vector3.zero, 100, 3, 1f);
}
4 相关知识点对比
DoTween 代码动画 VS 编辑器 Animation
DoTween:一行代码实现,无需制作动画资源,动态参数灵活;
Animation:需要手动关键帧,大量弹窗动画资源冗余。
5 模块拓展
弹窗关闭退场动画、按钮点击缩放反馈、数字滚动动画。
五、面向对象项目开发规范
1 概念
开发时优先抽取共性代码放入父类、管理器,功能实现后持续优化重构,应对策划频繁改需求,降低后期维护成本。
2 特性 / 规则
-
新增界面仅需:JSON 配置 + 新建继承 BasePanel 脚本,管理器代码无需改动;
-
重复逻辑全部封装通用方法,禁止每个界面重复编写查找、关闭、暂停代码;
-
分层:管理器做调度、基类做通用 UI 逻辑、子类只写当前界面特有业务;
-
避免硬编码字符串,统一使用枚举、配置表。
3 相关知识点对比
一次性写完不重构 VS 分层抽取架构
一次性开发:需求改动大面积修改代码,易出 Bug;
分层架构:新增 / 删除功能仅改动局部代码,可维护性强。
4 模块拓展
进阶商业项目架构 MVC 分层,分离视图、数据、控制层。
综合拓展
1 整套 UI 框架完整执行流程:游戏启动加载 JSON 配置→UIManager 解析存字典→点击按钮调用 PushPanel→反射创建界面→执行 BasePanel.Open 带 DoTween 入场动画→入栈暂停下层→关闭执行 PopPanel 恢复栈底交互。
2 高频 Bug 排查清单
弹窗下层可点击:检查 Pause 方法是否关闭 GraphicRaycaster;
关闭按钮无响应:确认物体名称为 CloseBtn、Open 内是否完成绑定;
DoTween 动画无效果:引入 DG.Tweening 命名空间;
栈长度异常:主界面禁止调用 Pop 出栈。
3 面试高频考点
Stack 栈实现弹窗层级、虚函数与抽象函数区别、DoTween 适用场景、反射动态创建界面优势、UI 架构分层思想。
4 实战落地要求
重构之前登录、背包项目,使用本套栈 + BasePanel+JSON 架构,写入简历体现工程化开发能力。