53.FGUI基础知识总结

  1. 53.总结
    1. 53.1 知识点
      1. 学习的主要内容
      2. 必须达到的水平
      3. 学会举一反三
      4. FairyGUI相对其它UI的优势
    2. 53.2 核心要点速览
      1. FairyGUI 是什么
      2. 从编辑器到游戏里看见界面
      3. 优缺点
      4. 为什么还要专门学它(即使 UGUI 更「主流」)
      5. UI 在项目里的权重
      6. 编辑器与工程目录
      7. 编辑器内的项目设置
      8. 包、依赖与资源地址
        1. 分包建议(工程习惯)
      9. 组件与发布产物
      10. 发布设置与 Unity 侧文件
      11. Unity 中加载与内存习惯
      12. UIPanel、动态创建与相机缩放
      13. StageCamera、UIContentScaler、UIConfig
      14. GObject 与元件分类
      15. GImage 与贴图资源
      16. GGraph 图形
      17. GMovieClip 序列帧
      18. 骨骼动画:Spine 与 DragonBones
      19. GLoader 与 GLoader3D
      20. 文本控件:普通文本、富文本与输入文本
        1. GTextField 普通文本
        2. 字体处理
        3. GRichTextField 富文本
        4. GTextInput 输入文本
      21. 组、控制器与关联系统
        1. GGroup 组
        2. Controller 控制器
        3. 关联系统
      22. 标签与按钮
        1. GLabel 标签
        2. GButton 按钮
      23. 进度条、滑动条与滚动条
        1. GProgressBar 进度条
        2. GSlider 滑动条
        3. GScrollBar 滚动条
      24. 滚动容器与列表
        1. ScrollPane 滚动容器
        2. GList 列表
      25. GComboBox 下拉框
      26. 组件拓展类与代码绑定
        1. 自定义组件拓展
        2. 自动代码生成
      27. 分辨率自适应
        1. 缩放模式
        2. 全屏适配
      28. 坐标系统
        1. 坐标转换 API
      29. 输入处理
        1. 触摸检测
        2. 手势识别
        3. 键盘输入
      30. 事件机制
        1. 事件传播
        2. 常用事件
      31. 拖拽功能
        1. 基础拖拽
        2. 拖拽替换
      32. 插入 3D 对象与粒子
        1. GoWrapper
        2. 注意事项
      33. DrawCall 优化
        1. Fairy Batching
        2. 优化原则
      34. 分支管理
        1. 分支机制
        2. 控制器联动
      35. 多国语言
        1. 字符串管理
        2. 动态文本
      36. 树控件
        1. GTree 与 GTreeNode
        2. 基本用法
      37. 窗口管理
        1. Window 基础
        2. 生命周期
        3. 高级功能
      38. 弹出功能
        1. Popup 与 ContextMenu
      39. 曲面 UI
        1. UIPainter
        2. 使用场景
      40. 动效系统
        1. Transition
        2. API 用法
        3. 动效类型
      41. 其他功能
        1. 颜色空间
        2. 偏好设置
    3. 53.3 面试题精选
      1. 基础题
        1. 1. FairyGUI 的整体架构大概长什么样?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 包、依赖和 ui:// 地址在面试里怎么说才像干过活?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. GImage 和 GLoader 什么时候用哪一个?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      2. 进阶题
        1. 1. 从「在编辑器里画完界面」到「Unity 里跑起来」,中间最关键的三步是什么?产物分别是啥?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. UIPackage.AddPackage 和挂在场景里的 UIPanel,各自在「谁能自动加载包」上有什么区别?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. 改「宽高」和改「scale」在 FairyGUI 里后果有什么差别?序列帧动画和图集分页是什么关系?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      3. 深度题
        1. 1. FairyGUI 相对 UGUI,在团队分工和工程风险上各有什么取舍?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 为什么说「默认加载包不等于立刻吃满显存」?卸载时要注意什么?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. FairyGUI 里嵌 Spine / 龙骨,着色器和预乘设置不对会怎样?Unity 还要做什么宏?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        4. 4. GTextField、GRichTextField、GTextInput 有什么区别?什么时候用哪一个?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        5. 5. GList 的虚拟列表是什么?开启虚拟列表要满足哪些前提?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        6. 6. Controller 控制器如何实现组件的多状态切换?属性控制有哪些类型?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        7. 7. FairyGUI 的事件冒泡机制是怎样的?如何阻止事件传播?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        8. 8. FairyGUI 的 DrawCall 优化有哪些关键手段?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章

53.总结


53.1 知识点

学习的主要内容

必须达到的水平

学会举一反三

FairyGUI相对其它UI的优势


53.2 核心要点速览

FairyGUI 是什么

  • 跨引擎的开源 UI 方案:不是某一个引擎插件的名字那么简单,而是一套「独立编辑器 + 各引擎运行时库」的组合。
  • 编辑器负责可视化拼装、动效与资源组织;运行时以各引擎 SDK 的形式存在,解析编辑器导出的数据并在游戏里绘制、响应输入。
  • 公开资料里常提到支持的引擎除 Unity 外,还包括 Unreal、Cocos2dx、Egret、LayaAir、Flash 等;跨引擎是特点,也意味着「不是所有引擎分支都同等成熟」——后面谈缺点会回到这一点。

从编辑器到游戏里看见界面

工程上可以记成一条顺序很硬的流水线,后面各篇都是在填这条线上的细节:

  1. FairyGUI 编辑器里把界面搭好,完成结构摆放与资源引用。
  2. 发布 / 导出:得到 图集(Atlas)和描述 UI 结构的 配置文件 等运行时真正要读的资源。
  3. 把资源放进 Unity(或其它引擎)工程,引用对应引擎的 FairyGUI 运行库,再写脚本完成显示、切换、数据绑、动效触发等逻辑层工作。

直觉理解:美术/策划在编辑器里「摆界面」,程序在引擎里「接数据、接玩法」;中间靠图集 + 配置把两边粘起来。

优缺点

方向 要点
优点 分工友好:界面拼装集中在 FairyGUI 编辑器里完成,美术可以不深入学 Unity 编辑器也能大量产出界面资源。迁移:同一套 UI 资源在「支持列表内」的引擎之间挪动,比纯 UGUI Prefab 绑死一套引擎要现实得多。功能面:相对 UGUI / NGUI,内置控件、动效、列表等全家桶更齐,少写大量自研封装。
缺点 跨引擎带来的长尾:非 Unity 等主流分支上可能遇到文档薄、坑多、修得慢的问题。Unity 上相对稳定——这也是很多团队敢选它的前提之一。

选型时不要抽象站队,而是看:团队里谁能做界面、项目是否要照顾多引擎、现有代码栈已经压在 UGUI 还是 FGUI 上

为什么还要专门学它(即使 UGUI 更「主流」)

  • 招聘与存量项目:市面上仍有不少在研/在运项目基于 FairyGUI,简历里写「能接包、能排查 FGUI 显示与 DrawCall」是实打实的加分项。
  • 能力维度:跨引擎 + 自带的一堆 UI 特性,在 Unity 里常被评价为「做复杂界面、动效、列表比纯 UGUI 省心」——当然代价是学习成本和引擎生态绑定方式不同。
  • 工作流:把「拼界面」尽量留在 FairyGUI 里,程序少在 Unity 里手摆 RectTransform,多写系统与玩法,分工更清晰。

UI 在项目里的权重

  • 2D、3D 游戏都极度依赖 UI:登录、HUD、背包、商店、引导……绝大多数功能都会落到界面上。
  • 对客户端来说,UI 往往不是「附属脚本」,而是常年要维护的一条主线,和渲染、网络一样值得系统学。

编辑器与工程目录

  • 编辑器:官网获取安装包;Unity 侧常见入口是 Asset StoreFairyGUI 装 SDK。先把「编辑器产资源 → Unity 加载运行」跑通,再啃功能细节。
  • 新建工程:路径不要中文;可勾选「在此位置创建子目录」,让工程外层多套一层文件夹,后期好搬。
  • 目录习惯assets 下每个子目录对应一个assets_分支名分支差异资源;settings 存工程配置;.objs 是编辑器内部缓存,一般不加入版本库与他人共享.fairy 是工程标识,双击即可打开工程,文件名可与项目名对齐。

编辑器内的项目设置

  • 基本:项目名、项目类型等工程级信息。
  • 默认值:影响的是编辑器里新建文本等资源时的默认字体、颜色、字号,并非直接改写运行时逻辑;配好后要点应用,之后新建资源会跟默认值走。
  • 快捷菜单:控件检查器旁下拉即可快改字体、字号、颜色,少进弹窗。
  • 适配:先选缩放模式(物理屏与逻辑屏是否一致),再在开「按屏幕缩放」时选适配模式——同时照顾宽高适合横竖屏切换、锁宽适合竖屏、锁高适合横屏;设计分辨率是后面一切比例计算的基准;可加设备分辨率列表在编辑器里预览不同机型。

包、依赖与资源地址

  • 是 FairyGUI 里组织资源的边界:assets 下一文件夹就是一个包;发布以包为单位;每个包里有 package.xml 记资源关联,丢或乱改都会出大问题。
  • 发布后典型得到描述文件 + 至少一张图集;运行时靠描述驱动怎么用图集把界面建起来。
  • 跨包引用:引擎不会替你解析依赖——A 里用了 B 的元件,运行时必须加载 B,再指望 A 正常工作。
  • 导出:要被别的包引用或要在代码里稳定 CreateObject 的组件,须在库里标导出(资源缩略图一角小红点);没导出则对外不可见也不能随便动态创建。
  • 资源 URL:规范写法是 ui:// + 包名 + 资源名,不拼文件夹路径,因此同一包内资源名别撞车;编辑器右键「复制 URL」拿到的是一类地址,手写时也能按规则拼接。

分包建议(工程习惯)

做法 适用
公共素材集中放一个公共包 多处共用的图标、通用底板
业务按模块拆包 登录、背包、排行榜各一包,边界清晰
小项目单包到底 体量小、无复杂依赖时省事
避免 A→B→C 链式依赖、避免交叉引用 加载顺序和调试成本会指数变差

组件与发布产物

  • 组件就是舞台里操作的那个容器:里面摆图片、动效、子组件;发布后 Unity 常以组件为最小创建单位。底层是一份 XML
  • 尺寸约束(最小/最大):约束的是被别的组件引用时允许的尺寸范围,不会自动改你现在舞台上的宽高。
  • 轴心 / 锚点:旋转、缩放绕着轴心转;勾选同时作为锚点后,位置计算会跟着轴心走;可记 轴心偏变换,锚点偏布局与关联
  • 溢出:可见、裁剪、或简易滚动;溢出模式不能在运行时改,定稿要早。
  • 自定义遮罩:运行时才好看清;带遮罩的组件往往不能把内外侧元件随便合成更少 DrawCall,做合批优化时要提前规划。
  • 点击测试 / 穿透:不规则点击区用图形或多边形;透明图做像素级点击时,图须与组件同包且不能用装载器代替直图。点击穿透打开后,空白区域不抢事件,叠 UI 时好用。
  • 设计图:只对拼图辅助,不进发布包

发布设置与 Unity 侧文件

  • 发布窗口:先全局、后单包较不容易漏项。路径里需要手写相对路径时注意 正斜杠;可用 {publish_file_name} 等变量拼输出目录。
  • Unity 平台描述文件扩展名常固定为 bytes二进制描述相对 XML 更省内存和解析开销,新项目能开则开。
  • 纹理集:限制最大边长、允许自动分页;分页 ≠ 手动拆多张纹理集;动画、位图字体与分页有兼容性限制,规划图集时要避开文档提到的坑。
  • Unity 下 分离 Alpha 常见是为了贴图格式与省内存;但在发布窗口把纹理集压成 PNG8 往往不如交给 Unity Import 设置,否则可能只劣化画质、体积收益有限。
  • 「发布文件名」和「包名」不是同一个东西:加载包时常用发布文件名CreateObject 用的是包名——两个串对不上会直接懵。
  • 资源库里的对象要先标导出再发布,否则描述和图集可以是空的。只改布局不改图时可用仅发布定义省掉重打大图集时间。
  • 若开 代码绑定XXXBinder.BindAll() 必须排在任何 UI 创建之前;实例用 CreateInstance,不要手写 new 绑定类。

Unity 中加载与内存习惯

  • 资源路径:Resources 子目录AssetBundle(整包或定义/资源分包两种做法正文都有示例)。
  • Unity Import:Default、关 Mip Maps、Filter 常用 BilinearMax Size 常卡 2048;压缩格式按平台换 DXT5 / ETC1 / PVRTC 等减内存。
  • UIPackage.AddPackage:走 Resources 时自带重复包检测;走 AB 时不帮你防重复加载,要自己把关。
  • 有依赖就 **遍历 dependencies 按名补 AddPackage**,顺序错了首屏必花。
  • 不要用 Destroy 凑合掉 FGUI 对象,面板生命周期走 Dispose 这一套。
  • 默认 延迟加载贴图AddPackage 先吃描述,用到才真正拉贴图;要暖机可 LoadAllAssets()。卸载 RemovePackage 会清掉包内资源,已经和那张包绑定的界面会废;频繁装卸费 CPU、GC 猛,常驻包要想清楚。若 AB 想自己管,unloadBundleByFGUI 可以关掉 FGUI 的自动 Unload 行为。

UIPanel、动态创建与相机缩放

  • UIPanel:层级菜单 FairyGUI → UIPanel;Inspector 里点包名、组件名会弹选择器——只列已进 Unity 工程已导出的组件;改发布记得 Refresh
  • 硬限制:挂在场景里的 UIPanel 只会自动从 Resources(含子目录) 拉包;AB 里的必须你先在代码 AddPackage 好。
  • 动态建 UIPanelAddPackageGameObjectUI 层AddComponent<UIPanel> → 填包名/组件名 → 调 CreateUI();渲染模式、Fairy Batching、排序等多从 container 和面板 API 走。
  • SortingOrder 在 Screen Space 下 1000 像条「分水岭」,和 Unity 传统 2D UI 谁压谁有关;World Space 想按 Z 排要配合 SortWorldSpacePanelsByZOrder,但飘字、血条这类通常仍建议 Screen Space + 坐标换算,别硬上 World Space 自找排序麻烦。
  • 代码直创 UISetContentScaleFactor(或等价组件)→ AddPackage → 补依赖包 → CreateObject / CreateObjectAsyncGRoot.inst.AddChild;销毁走 Dispose。项目一大,纯 UIPanel 堆场景很难维护,动态创建更适合接 MVC / UI 栈等套路;正文提醒:动态创建的 FGUI 树别和别的 GameObject 强耦合

StageCamera、UIContentScaler、UIConfig

  • StageCamera 就是 UI 相机;首次动态创建 UI 或建 UIPanel 时常自动生成一份,也可手动 FairyGUI → UI Camera。上面 UICameraConstant Size 管粒子等是否跟屏幕缩放,手机 / PC 取向不同。
  • UIContentScalerGRoot.inst.SetContentScaleFactor 等价二选一;场景里任意物体挂一份即可,不必每个场景重复挂载。
  • UIConfig:编辑器里设的「全局默认」进了 Unity 不会自动生效;要用 UIConfig 组件配默认字体、按钮音、音量等。Preload Packages 里填 Resources 下的包名 做启动预载;Config Items 里路径可写 Resources 或 ui://

GObject 与元件分类

  • 舞台上的最小单位是元件GObject 是所有 UI 元素的基类,GComponent(组件)继承自它,面板、列表等容器都是组件。
  • 基础元件包括图片、图形、动画、装载器、文本、富文本、组、组件;组合型如标签、按钮、下拉框等;列表是特殊的一类。
  • 名称允许重复但编辑器会警告;真正要稳定 GetChild("xxx") 的节点,在同一面板里仍建议唯一
  • 尺寸和缩放不是一回事:拉宽高会触发九宫格、不会把子物体一起缩放;改 scale 会把子级一起放大缩小;关联系统只认宽高变化,不把你设的 scale 算进关联条件
  • 保持比例:主要是编辑时拖大小的辅助;若要在运行时按比例自适应,更像原文说的——把图放进装载器并选「适应高度/宽度」等填充策略。
  • 倾斜:图片、动画、装载器用它做伪 3D 相对便宜;其它类型要谨慎。
  • 触摸:默认图片、普通文本、动画不处理点击;要响应事件需换成组件、富文本、装载器等可触摸路径。
  • 变灰:除整体颜色滤镜外,组件里可以做一个名为 grayed 的控制器,分项控制哪些子件参与置灰。
  • 混合模式 / 滤镜:Unity 里在图片、动画、文字上动它相对安全;乱加到复杂组件上容易涨内存、涨 DrawCall
  • 运行时访问:displayObject.gameObject 可拿到挂载侧对象;Dispose 回收;resourceURLpackageItem 等在承载资源的元件上才有意义。

GImage 与贴图资源

  • GImage:定位是简洁、静态不能像装载器那样日常换 url默认也不可点击;需要切图或点击请用 GLoader
  • 资源库内可配置九宫格、平铺、平滑、纹理集归属(默认打包 / 单独一张 / 指定集编号等)、边缘像素重复(防平铺裂缝)、是否允许发布时剪透明边等。
  • 填充裁剪与发布选项里的「裁剪图片边缘空白」可能打架——需要特殊填充时,常在图片属性里勾选禁止裁剪边缘空白,否则位移会怪。
  • 翻转走渲染路径,不等同于scale 设为 -1;个别非 Unity 分支的实现仍可能用 scale 模拟,避免混用两套翻转手段。
  • Unity 里 view.GetChild("...").asImage,常用 fillAmountfillMethod,或 texture = new NTexture(sprite) 喂引擎贴图;动态 CreateObject 出图片时记得资源在库里已导出
  • 多倍图:例如 a.pnga@2x.png 一起发布,并在发布设置里勾好对应后缀,运行时按缩放系数选用高清档,一般不必手写切换表。

GGraph 图形

  • 支持空白、矩形、椭圆、正多边形、可编辑多边形等;典型用途:遮罩、占位、雷达图、箭头轮廓等矢量示意。
  • DrawRectDrawEllipse 等 API 重绘会盖住之前的形状;脚本里 new GGraph()DrawXXXAddChild 很常见的拼接方式。
  • 空白图形侧可走 SetNativeObject 把 Unity 侧对象嵌进 FGUI(与后续专题衔接)。

GMovieClip 序列帧

  • 动画素材在工程里落成 jta;来源可以是 Flash/Animate 导 plist、eas + 贴图拖入、编辑器里组序列、或 GIF 直接拖入转换。
  • 时间轴侧:帧频、间隔帧、循环间隔、单帧停留、摆动播放(正播倒播往返);序列帧占用的所有格图必须在同一纹理集,因为不支持纹理分页——规划图集时要给动画留位。
  • Unity:asMovieClipplayingframeSetPlaySettings 控制区间与循环;onPlayEnd 做播放结束回调。

骨骼动画:Spine 与 DragonBones

  • 当前支持范围按教材:Spine 3.8 导出、DragonBones 各版本导出;导入时只需骨骼描述文件(如 .json/.skel.json/.dbbin),不必把骨骼当成普通单张 UI 图那条导入链硬套。
  • 资源面板里可选着色器:Default(骨骼库默认;要遮罩可能走自定义遮罩思路)、FGUI/Image(可走常规矩形遮罩,但须和预乘匹配,否则颜色发灰/发边)。
  • 贴图是否预乘必须与 DCC 导出设置一致,否则显示必偏。
  • Unity 工程:安装对应 Spine / 龙骨 Unity 运行时,在 Scripting Define Symbols 增加 FAIRYGUI_SPINEFAIRYGUI_DRAGONBONES;龙骨流程里往往还要生成 Unity Data
  • 与骨骼结点交互:从 GObject.displayObject.gameObject 往下找具体骨骼组件,再调用各 SDK 的播放、换装 API。

GLoader 与 GLoader3D

  • GLoader:通过改 url 动态切换 图片、动画、组件;可写 ui://包名/资源名,也可在工程约定下写 Resources 相对路径
  • 发布时清除 URL:避免把编辑器里临时拖进去看的资源路径打进正式包。
  • 自动大小:开启后装载器尺寸跟内容走,此时再调填充模式没有意义。
  • 填充模式:无缩放、等比留边、等比铺满、适应高/宽、自由拉伸等;另有仅允许缩小,防止小屏被暴力放大糊掉。
  • 自定义加载管线:继承 GLoader,在 LoadExternal 里异步/同步拿到 NTexture 后调用 onExternalLoadSuccess,失败走 onExternalLoadFailed;释放覆写 FreeExternal;用 UIObjectFactory.SetLoaderExtension 把全局装载器实现换成你的子类(注意全局影响面)。
  • GLoader3D:面向更重的 Spine / 龙骨 等;编辑器侧能力可能受授权/版本限制;本身不做矩形剪裁,要裁超出区域需外层包一层溢出隐藏的组件。

文本控件:普通文本、富文本与输入文本

GTextField 普通文本

  • 定位:纯显示,不支持交互、超链接、图文混排、HTML;需要这些功能请用富文本。
  • UBB 语法:普通文本支持 [color][size][b][i][u] 等样式标签,但 **不支持 [img][url]**。
  • 文本模板:用 {count=100} 声明参数,运行时 SetVar("count", "200").FlushVars() 动态替换;适合多语言、数值变化频繁的文本。
  • 自动大小:无(固定宽高)、自动宽高、自动高度(固定宽度换行)、自动收缩(缩小字号适配)、显示省略号。
  • 描边 / 投影:共用一个颜色设置;各引擎实现有差异,编辑器效果仅供参考。
  • Unity APItexttextFormat.sizetextFormat.coloralignverticalAlignsingleLine 等;动态创建用 new GTextField()

字体处理

字体类型 说明 注意事项
系统字体 不建议 跨设备字体名可能不存在,效果不可控
TTF 字体 最常用 发布后字体文件不进包,需手动放 Unity 并注册
位图字体 特殊需求 用图片表示字符,支持 BMFont 导出的 fnt 文件
  • TTF 字体注册:放 ResourcesResources/Fonts 下自动注册;其他路径需 FontManager.RegisterFont(new DynamicFont("名字", font))
  • 默认字体:编辑器设的默认字体进 Unity 不生效,要用 UIConfig.defaultFont 或 UIConfig 组件配置。
  • TextMeshPro 支持:字体渲染方式设为 SDFAA,Unity 加 FAIRYGUI_TMPRO 宏。

GRichTextField 富文本

  • 与普通文本的区别:支持交互超链接图文混排HTML 语法
  • UBB 扩展[img]ui://包名/图片名[/img][url=地址]文字[/url]
  • HTML 语法<img src='ui://包名/图片名'/><a href='xxx'>link</a>,支持 width/height 百分比。
  • 超链接样式:全局用 HtmlParseOptions.DefaultLinkColor 等;单个富文本用 htmlParseOptions.linkColor
  • 超链接点击onClickLink.Add((ctx) => { string data = ctx.data.ToString(); }),data 不一定是网址,可自定义规则做面板跳转等。

GTextInput 输入文本

  • 用途:接收用户输入文字。
  • 属性maxLength(最大长度)、displayAsPassword(密码模式)、restrict(正则限制)、keyboardType(手机键盘类型)、promptText(提示文字)。
  • 事件onChanged(内容变化)、onFocusIn/onFocusOut(焦点进出)、onSubmit(单行模式下回车确认)。
  • APIRequestFocus() 主动获取焦点;SetSelection(0, 4) 选中指定范围。

组、控制器与关联系统

GGroup 组

  • 普通组:仅编辑时有效,辅助整体移动、调整深度、复制粘贴;发布后不存在。
  • 高级组:发布后保留,可代码控制显隐、位置、布局。
  • 布局模式:无(仅控制显隐)、水平布局、垂直布局;行列距、排除隐藏对象、禁用自动计算包围等。
  • Unity APIgGroup.visiblegGroup.layout;无法直接获取组内子对象,需遍历 view.numChildren 判断 GetChildAt(i).group == gGroup

Controller 控制器

  • 核心作用:为组件添加多状态切换能力,实现分页、按钮状态、属性变化等。
  • 创建:组件内可建多个控制器;控制器名不要重名;页面索引从 0 开始。
  • 属性控制类型
控制类型 说明 支持缓动
显示控制 指定页面显示/隐藏元件
位置控制 不同页面不同 XY 坐标
大小控制 不同页面不同宽高/Scale
颜色控制 不同页面不同颜色(图片/文本/装载器)
外观控制 不同页面不同透明度/变灰/旋转/不可触摸 部分
文本控制 不同页面不同文本内容
图标控制 不同页面不同图标 URL
动画控制 不同页面不同播放状态/帧
字体大小控制 不同页面不同字号
  • Unity APIselectedIndex(切换页面,触发事件)、SetSelectedIndex(不触发事件)、selectedPage(按名字切换)、onChanged 监听切换;GearBase.disableAllTweenEffect = true 关闭所有缓动。
  • 联动:按钮可绑定控制器,点击时自动切换控制器页面。

关联系统

  • 定位:FairyGUI 自动布局核心,类似 UGUI 锚点但更灵活——可定义任意两个元件之间的关系。
  • 关联类型:横向(左左、左右、右左、右右、宽度百分比等)、纵向(顶顶、顶底、底顶、底底、高度百分比等)。
  • 关键点:关联只在目标元件位置/大小变化时生效;设置关联不等于居中/对齐,初始位置仍需手动设置。
  • Unity APIAddRelation(target, RelationType.Left_Left) 添加关联;RemoveRelation 删除某种关联;relations.ClearAll() 清空所有关联;relations.ClearFor(target) 清空与指定对象的所有关联。

标签与按钮

GLabel 标签

  • 本质:组合控件,至少包含 title(文本)和 icon(图片)两个元件。
  • 创建方式:自动创建(菜单 → 资源 → 新建标签);手动创建需新建组件并设扩展为标签,内部元件命名必须为 titleicon
  • Unity APItexticontitleColortitleFontSize;不转成 GLabel 也能直接用 GObject 的 text/icon 属性。

GButton 按钮

  • 三种模式:普通按钮(无状态)、单选按钮(选中后保持)、复选按钮(可切换选中状态)。
  • 命名规则:控制器名 button、文本 title、图片 icon
  • 设计属性
    • 声音:点击音效,可全局设置 UIConfig.buttonSound
    • 按下效果:缩放(改 Scale,轴心自动设为 0.5,0.5)、变暗(改所有图片颜色)。
  • 实例属性selected(选中状态)、texticon、选中时标题/图标。
  • Unity API
    • selected:获取/设置选中状态。
    • onClick:点击事件;FireClick(true, true) 模拟点击(第一个参数是否触发效果,第二个是否触发事件)。
    • onChanged:状态变化事件(单选/复选按钮常用)。
  • 音效控制GRoot.inst.EnableSound() / DisableSound() 开关音效;GRoot.inst.soundVolume 调整音量。

进度条、滑动条与滚动条

GProgressBar 进度条

  • 原理:按进度改变元件宽度、高度或填充比例。
  • 关键元件bar(横向,改变宽度)、bar_v(纵向,改变高度)、title(显示进度文本)、ani(序列帧动画,帧索引对应进度值)。
  • 标题类型:百分比、当前值/最大值、当前值、最大值。
  • 反向:进度条延伸方向相反。
  • Unity APIvalue 当前值;TweenValue(targetValue, duration) 缓动到目标值。
  • 关联增强:可在进度条内放一个元素与 bar 建立关联,实现进度变化时元素跟随移动的效果。

GSlider 滑动条

  • 与进度条的区别:增加可拖动的滑块按钮(grip),允许玩家手动改变值。
  • 关键元件barbar_vtitlegrip(拖动按钮);grip 需与 bar 建立关联。
  • 设计属性wholeNumbers(整数输入)、changeOnClick(点击滑动条改变值)。
  • Unity APIvalueonChanged 监听值变化。

GScrollBar 滚动条

  • 定位:配合滚动容器使用,不能单独拖到舞台。
  • 关键元件arrow1/arrow2(两端按钮,可选)、grip(滑块)、bar(滑动范围占位)。
  • 使用方式:在项目属性设置全局滚动条,或在滚动容器中单独指定。
  • 固定滑块大小:勾选后滑块不随内容比例变化。

滚动容器与列表

ScrollPane 滚动容器

  • 本质:组件的溢出处理设为「滚动」即成为滚动容器。
  • 滚动条显示:默认(全局设置)、可见、滚动时显示、隐藏。
  • 属性:边缘回弹、触摸滚动、惯性滚动、页面模式、下拉/上拉刷新组件等。
  • Unity API
    • posY/posX:滚动位置;SetPercY(0.5f, true) 按百分比滚动。
    • viewWidth/viewHeight:视口宽高;contentWidth/contentHeight:内容宽高。
    • ScrollToView(obj):滚动到指定元件可见。
    • touchEffect:触摸滚动开关。
  • 事件onScroll(滚动时)、onScrollEnd(惯性停止)、onPullDownRelease/onPullUpRelease(下拉/上拉刷新)。

GList 列表

  • 本质:组件的特殊扩展,加入排序功能。
  • 布局模式:单列竖排、单行横排、横向流动、竖向流动、分页。
  • 选择模式:无、单选、多选;单选需用单选按钮作为 item。
  • 对象池 API
方法 说明
AddItemFromPool() 从池中取出或新建对象添加到列表
RemoveChildToPool(obj) 删除 item 并返回池中
RemoveChildrenToPool() 删除所有 item 并返回池中
GetFromPool(url) 从池中取出对象(不添加到列表)
  • 回调渲染list.itemRenderer = RenderListItemlist.numItems = 30 会自动创建对象并调用回调初始化。
  • 虚拟列表SetVirtual() 开启,只渲染可见区域的 item,适合大数据量;前提是必须定义 itemRenderer、开启滚动、设置项目资源。
  • 循环列表SetVirtualAndLoop(),只支持单行或单列布局。
  • 事件onClickItem 点击 item。

GComboBox 下拉框

  • 组成:下拉框主体 + 弹出组件 + 下拉框 Item。
  • 弹出组件构成:背景图 + 垂直滚动列表(命名为 list)。
  • 属性:可见项目数、弹出方向(建议自动)、选择控制(绑定控制器联动)。
  • Unity API
    • itemsiconsvalues:代码初始化选项内容。
    • selectedIndex:当前选中索引;value:当前选中值。
    • onChanged:选择变化事件。
    • GRoot.inst.HidePopup():代码关闭弹出项。

组件拓展类与代码绑定

自定义组件拓展

  • 实现步骤:创建类继承 GComponent → 重写 ConstructFromXML 初始化控件 → UIObjectFactory.SetPackageItemExtension 注册关联。
  • ConstructFromXML:在组件从 XML 构建时调用,适合获取子控件引用、绑定事件;不要在构造函数里访问子控件,此时子控件还未创建。
  • 注册时机:必须在 CreateObject 之前完成注册,通常放在初始化阶段或 UIPackage.AddPackage 之后。
public class MyPanel : GComponent
{
    private GButton btnTest;
    private GTextInput inputTxt;

    public override void ConstructFromXML(XML xml)
    {
        base.ConstructFromXML(xml);
        btnTest = GetChild("btnTest").asButton;
        inputTxt = GetChild("inputTxt").asTextInput;
        btnTest.onClick.Add(() => Debug.Log("点击"));
    }
}

UIObjectFactory.SetPackageItemExtension("ui://包名/组件名", typeof(MyPanel));

自动代码生成

  • 编辑器导出代码后,Unity 侧调用 XXXBinder.BindAll() 完成注册;必须排在任何 UI 创建之前
  • 实例化用 CreateInstance,不要手写 new 绑定类;生成的类已包含子控件引用和事件声明。

分辨率自适应

缩放模式

  • SetContentScaleFactor:设置 UI 缩放基准,通常在启动时调用一次。
  • 设计分辨率:所有 UI 布局的参考尺寸,编辑器与运行时需保持一致。
  • 适配策略:同时适配宽高、只适配宽度、只适配高度;横屏游戏常锁高,竖屏游戏常锁宽。

全屏适配

  • MakeFullScreen:让组件铺满屏幕,自动处理安全区域。
  • 关联系统AddRelation 设置组件与父容器的对齐、尺寸关联关系,如 RelationType.WidthRelationType.Height

坐标系统

坐标转换 API

方法 作用
LocalToGlobal 局部坐标 → 屏幕坐标
GlobalToLocal 屏幕坐标 → 局部坐标
LocalToRoot 局部坐标 → GRoot 坐标
RootToLocal GRoot 坐标 → 局部坐标
TransformPoint 任意两个组件间坐标转换
  • GRoot:UI 的根容器,所有动态创建的 UI 都挂在其下;坐标原点在左上角。
  • 屏幕坐标:Unity 屏幕空间坐标,Y 轴向下;与 Unity 世界坐标(Y 轴向上)不同。

输入处理

触摸检测

  • Stage.isTouchOnUI:判断当前触摸是否落在 UI 上,常用于区分「点 UI」和「点 3D 场景」。
  • InputEvent:封装触摸位置、按钮状态、滚轮等信息。

手势识别

  • FairyGUI 内置常见手势:点击、双击、长按、滑动、缩放、旋转。
  • 手势通过 onClickonRightClickonTouchBegin/End/Move 等事件实现;复杂手势可结合时间与位移判断。

键盘输入

  • Stage.GetTouchStage.GetTouchPosition 获取触摸信息。
  • Input.GetKeyDown 等 Unity API 仍可使用,但要注意 UI 焦点状态。

事件机制

事件传播

  • 冒泡机制:事件从目标元件向上传播到父级组件,直到 GRoot。
  • EventContext:包含事件数据,sender 是事件发起者,initiator 是实际触发者。
  • StopPropagation:阻止事件继续向上冒泡。
  • CaptureTouch:捕获触摸,即使手指移出元件范围仍能收到后续事件。

常用事件

事件类型 说明
onClick 点击
onRightClick 右键点击
onTouchBegin/End/Move 触摸开始/结束/移动
onRollOver/Out 鼠标进入/离开
onKeyDown/Up 键盘按下/抬起
onChanged 内容变化(文本、列表等)

拖拽功能

基础拖拽

  • draggable:设为 true 启用拖拽。
  • dragBounds:限制拖拽范围,传入 Rect
  • onDragStart/Move/End:拖拽开始/进行中/结束的回调。

拖拽替换

  • StartDrag:代码启动拖拽,可指定拖拽代理(拖拽时显示的图标)。
  • 拖拽结束通过 onDrop 事件处理放置逻辑。

插入 3D 对象与粒子

GoWrapper

  • 作用:将 Unity 的 GameObject 包装成 FGUI 元素显示在 UI 中。
  • SetNativeObject:把 Unity 对象挂载到 FGUI 控件上。
  • CacheRenderers:缓存渲染器引用,避免每帧 GetComponent
GoWrapper wrapper = new GoWrapper();
wrapper.SetNativeObject(my3DObject);
parent.AddChild(wrapper);

注意事项

  • 3D 对象的渲染层级由 FGUI 管理,但材质、Shader 需自行处理。
  • 粒子系统同样通过 GoWrapper 嵌入,注意粒子材质与 UI 的渲染顺序。

DrawCall 优化

Fairy Batching

  • fairyBatching:开启后 FGUI 会尝试合并渲染批次,减少 DrawCall。
  • InvalidateBatchingState:手动触发深度重算,适用于动态改变层级或显示隐藏后。

优化原则

  • 同一图集的元素尽量相邻摆放,减少材质切换。
  • 避免频繁改变 UI 结构,每次变动都可能触发重排。
  • 合理使用 overflow 隐藏,减少不必要的渲染区域。

分支管理

分支机制

  • UIPackage.branch:设置当前分支,加载资源时会自动映射到对应分支目录。
  • 分支目录命名assets_分支名,如 assets_cnassets_en
  • 资源映射:同一资源名在不同分支下可以有不同内容,运行时按分支自动切换。

控制器联动

  • 控制器页面名可与分支名对应,实现「切换控制器 = 切换分支资源」的效果。

多国语言

字符串管理

  • 导出字符串:编辑器导出多语言文本表(XML 或 JSON 格式)。
  • 翻译流程:导出 → 翻译 → 导入;支持增量更新。
  • SetStringsSource:运行时加载翻译后的字符串表,UIPackage.SetStringsSource(xml)

动态文本

  • 文本模板{count=100} 声明参数,运行时 SetVar("count", "200").FlushVars() 替换。
  • 适合数值变化频繁的文本,如「剩余 {count} 次」。

树控件

GTree 与 GTreeNode

  • GTree:继承自 GList,专门用于树形结构展示。
  • GTreeNode:树节点,包含 dataexpandedparent 等属性。
  • treeNodeRender:自定义节点渲染回调,根据数据设置节点外观。
  • treeNodeWillExpand:节点展开前回调,可异步加载子节点。

基本用法

GTree tree = GetComponent<GTree>();
tree.treeNodeRender = (node) => {
    node.text = node.data.ToString();
};
tree.rootNode.AddChild(new GTreeNode(true, "folder"));

窗口管理

Window 基础

  • Window:FairyGUI 提供的窗口基类,封装了显示、隐藏、模态等功能。
  • contentPane:窗口内容面板,通过 UIPackage.CreateObject 创建。
  • modal:设为 true 后窗口为模态,背景会遮挡其他 UI。

生命周期

方法 调用时机
OnInit 窗口首次创建
OnShown 窗口显示时
OnHide 窗口隐藏时
Dispose 窗口销毁

高级功能

  • ShowModalWait:显示模态等待遮罩,锁定窗口。
  • CloseModalWait:关闭等待遮罩。
  • BringToFront:将窗口置顶。
  • Show / Hide:显示/隐藏窗口。

弹出功能

  • ShowPopup:在指定位置弹出组件,GRoot.inst.ShowPopup(content, initiator, direction)
  • HidePopup:关闭当前弹窗,GRoot.inst.HidePopup()
  • PopupMenu:右键菜单类,支持添加菜单项和分割线。
PopupMenu menu = new PopupMenu();
menu.AddItem("复制", (EventContext context) => { /* 处理 */ });
menu.AddItem("粘贴", null);
menu.Show();

曲面 UI

UIPainter

  • 作用:将 FGUI 渲染到 3D 曲面上,实现曲面屏、圆柱屏等效果。
  • VUI 层:专门用于曲面 UI 的渲染层。
  • Hidden VUI:隐藏层,用于不显示但需要计算的曲面 UI。

使用场景

  • 游戏内曲面屏幕(如街机、监控器)。
  • VR/AR 中的曲面界面。
  • 特殊视觉效果的 UI 展示。

动效系统

Transition

  • Transition:FairyGUI 内置动效类,支持位移、缩放、旋转、透明度、颜色等属性动画。
  • 关键帧:在编辑器时间轴上设置关键帧,运行时自动插值。
  • Play / Stop / SetPaused:播放、停止、暂停动效。

API 用法

Transition trans = component.GetTransition("show");
trans.Play();                              // 播放
trans.Play(() => Debug.Log("完成"));       // 播放并回调
trans.SetPaused(true);                     // 暂停
trans.Stop(false, true);                   // 停止并重置到起始状态

动效类型

类型 说明
XY 位置动画
Size 尺寸动画
Scale 缩放动画
Rotation 旋转动画
Alpha 透明度动画
Color 颜色动画

其他功能

颜色空间

  • Linear / Gamma:FairyGUI 支持切换颜色空间以匹配项目渲染管线。
  • 在 UIConfig 或启动代码中设置。

偏好设置

  • UIConfig:全局配置类,可设置默认字体、按钮音效、模态遮罩颜色等。
  • StageSoundVolume:UI 音效音量。

53.3 面试题精选

基础题

1. FairyGUI 的整体架构大概长什么样?

题目

一句话说明 FairyGUI 相对「纯引擎内嵌 UI」多了哪一层,以及「编辑器侧」和「运行时侧」各自负责什么。

深入解析
  • FairyGUI 是跨引擎方案:核心不是某个 MonoBehaviour 封装,而是独立编辑器 + 多引擎 SDK
  • 编辑器:可视化编辑、资源打包规则、动效与组件描述等,最终产出图集配置文件(具体扩展名与字段以导出设置和工具版本为准)。
  • 运行时:各引擎上的 FairyGUI 库读取上述资源,负责网格合并、显示对象树、输入、动效状态机等与引擎对接的部分。
  • UGUI 对比记忆:UGUI 的权威来源是 Unity 编辑器里的 Canvas + Prefab 工作流;FGUI 的权威来源是 FairyGUI 编辑器导出的数据 + 引擎侧 SDK。
答题示例

FairyGUI 是独立 UI 编辑器加各引擎运行时 SDK,中间用图集和配置文件交付。

编辑器负责排版和资源组织,运行时 SDK 在 Unity 里加载包、创建显示对象并处理逻辑与交互。

参考文章
  • 1.概述

2. 包、依赖和 ui:// 地址在面试里怎么说才像干过活?

题目

说明「包」在磁盘与发布结果里分别长什么样;跨包用资源时要满足哪些条件、加载顺序怎么保证;手写资源地址时规则是什么、为什么要求包内资源名不重复。

深入解析
  • 磁盘assets 下一目录通常就是一个包;包内有 package.xml 记录资源关系。发布后得到描述数据 + 图集,Unity 常见描述后缀为 bytes
  • 依赖:运行时不会自动替你加载依赖包;A 引了 B 的资源,必须先 AddPackage B(或通过 dependencies 枚举再加载),否则显示异常。
  • 导出:跨包引用的资源须标导出(缩略图小红点);需要代码 CreateObject 的组件一般也要能对外导出,否则访问不到。
  • URLui://包名/资源名不含文件夹路径,因此同一包内资源名冲突会直接乱套。
答题示例

包在工程里是一个目录,发布出去是描述文件加图集;package.xml 是包的索引。

跨包用资源要先加载被依赖包,导出要打红点;地址用 ui://包名/资源名,所以包内资源名要唯一。

参考文章
  • 5.包的概念
  • 8.加载包

3. GImageGLoader 什么时候用哪一个?

题目

各解决什么问题;为什么「不动态换图、不要点击」的底图更适合 GImage;要点点击或换头像时该怎么选。

深入解析
  • GImage:为静态显示优化,不能像装载器那样日常改 url,默认也不参与点击——适合背景、固定图标等资源在编辑期就定死的元素。
  • GLoader:核心是动态 url,可指向包内 ui:// 资源,也可按工程约定指向 Resources 等;可装图片、序列帧、子组件;需要运行时换皮、换图标、列表项模板时首选。
  • 性能直觉:能用纯图片解决的别硬上装载器;但一旦需求里有「同一格子换不同图」,装载器比反复 CreateObject 图片更贴合设计。
答题示例

GImage 适合不变的图,不能动态换资源,默认也不可点。

GLoader 用 url 动态换图、动画或组件,要点击或热更资源时用装载器。

参考文章
  • 14.GImage图片
  • 18.GLoader装载器

进阶题

1. 从「在编辑器里画完界面」到「Unity 里跑起来」,中间最关键的三步是什么?产物分别是啥?

题目

按时间顺序说出 FairyGUI 的典型工作流,并说明导出侧主要交付给程序的资源形态。

深入解析
  1. 编辑:在 FairyGUI 编辑器中完成 UI 结构与资源配置(包、组件、面板等资源组织方式由工程约定)。
  2. 导出:生成 图集(减少绘制批次的贴图打包结果)和 配置文件(描述界面树、控制器、关联等的数据;具体扩展名与发布选项以项目与版本为准)。
  3. 引擎接入:把资源导入 Unity,挂载/初始化 FairyGUI 运行环境(常见做法是挂载 UIPanel、按路径加载包、用 UIConfig 等对全局行为做一次性配置),再用脚本驱动逻辑。

踩坑提示:新人常只记得「拖 Prefab」,但在 FGUI 体系里要先建立「包是否加载、默认资源路径、缩放策略是否正确」的直觉,否则界面空白往往不是 C# 写错一行,而是资源管线没接通

答题示例

先在 FairyGUI 编辑器做界面,再导出图集和配置文件进 Unity,最后用 FairyGUI 的 SDK 加载包并写脚本逻辑。

程序最关心的是包有没有按路径加载成功、导出设置是否与运行时默认规则一致。

参考文章
  • 1.概述

2. UIPackage.AddPackage 和挂在场景里的 UIPanel,各自在「谁能自动加载包」上有什么区别?

题目

对比 Resources 路径加载与 AssetBundle 加载时,重复加载行为有何不同;场景里配置的 UIPanel 对资源位置有什么硬性要求;动态创建 UI 前通常要完成哪几步。

深入解析
  • ResourcesAddPackage(路径) 以传入路径为 key 做去重,重复调一般无害。
  • AssetBundleAddPackage(AB) 不做排重,同一 AB 多次加载要自己防。
  • UIPanel:Inspector 里选包、选组件很省事,但文档明确:只会自动载入放在 Resources(含子目录)下的包;AB 方案必须先代码 AddPackage
  • 动态流程:先 SetContentScaleFactor(或组件等价配置)确定逻辑分辨率策略 → AddPackage 主包遍历 dependencies 补依赖CreateObject / 异步版本GRoot.inst.AddChild;销毁用 Dispose,别跟 Unity Destroy 混用惯例。
答题示例

Resources 用 AddPackage 有去重,AssetBundle 没有,要自己防止重复加载。

UIPanel 只能自动拉 Resources 里的包,AB 必须先代码加载。

动态创建要先设缩放、加载包和依赖包,再 CreateObject 加到 GRoot,不用了 Dispose。

参考文章
  • 8.加载包
  • 9.UIPanel组件
  • 10.动态加载UI、GRoot和GComponent

3. 改「宽高」和改「scale」在 FairyGUI 里后果有什么差别?序列帧动画和图集分页是什么关系?

题目

从子物体是否跟着变、九宫格是否生效、关联系统是否吃 scale 三个角度对比;为什么文档强调序列帧动画必须落在同一纹理集。

深入解析
  • 宽高:驱动九宫格拉伸规则;不会把子节点连带缩放;关联系统监视的是宽高变化,不把 scale 的影响算进关联
  • scale:整体视觉缩放,子物体跟着变;与九宫格、关联的触发路径不同,别混用「想只改父级布局却去拧 scale」糊弄过去。
  • 序列帧 + 图集:序列帧动画在工具链里不支持纹理分页——帧图必须落在同一张图集;与「自动分页」冲突时要为动画单独划纹理集或减小帧图体量,否则发布阶段会报错。
答题示例

改尺寸走九宫格,不会缩放子对象,关联只看宽高;改 scale 会带动子级,关联不认 scale。

序列帧所有帧要在同一图集,因为动画不能做纹理分页,和自动分页要自己协调。

参考文章
  • 13.GObject元件
  • 16.GMovieClip序列帧动画
  • 7.发布UI

深度题

1. FairyGUI 相对 UGUI,在团队分工和工程风险上各有什么取舍?

题目

结合概述中的观点,谈谈「美术在 FairyGUI 里拼装界面」带来的好处,以及「跨引擎工具」可能引入的工程风险,并给出你在技术选型时会看的条件。

深入解析

分工与效率

  • 优点方向:界面制作尽量收敛在 FairyGUI 编辑器,程序少做「在 Scene 里手摆 UI」的劳力活,更专注玩法、网络、性能;美术也不被迫精通 Unity 编辑器里一整套 UI 工具链。
  • 和 UGUI 对比:UGUI 当然也能分工,但常见模式是美术出切图与规范,程序在 Unity 里搭 Prefab;FGUI 则把「搭界面」往前推到专用编辑器里完成。

跨引擎与维护风险

  • 缺点方向:工具链跨引擎,非 Unity 主线上的问题可能更依赖社区与自行踩坑;对插件版本、引擎大版本升级要额外留回归时间。
  • Unity 侧:业内在选型时常说 Unity 分支相对成熟,但「成熟」不等于零成本——包体、Shader、Stencil、DrawCall 等仍要按目标机型与画质档位做实测。

选型时可口述的判据(不必背标准答案,能说清即可)

  • 团队是否已有 FGUI 资产与规范、招聘市场里 FGUI 经验是否重要。
  • 界面复杂度与动效需求是否值得引入第二条 UI 管线。
  • 是否有多引擎或长期迁移需求。
  • 是否能接受双栈 UI(FGUI + UGUI)带来的认知与打包成本。
答题示例

FairyGUI 把界面拼装前移到独立编辑器,美术和策划能更深地参与界面搭建,程序专注逻辑,在复杂 UI 上常常比纯 UGUI 更顺手。

代价是引入跨引擎工具链,版本与分支上的问题要自己评估;Unity 上相对稳,但性能与兼容性仍要按项目压测。

选型会看团队现有栈、界面复杂度、是否要跨引擎,以及能不能维护好包加载与 DrawCall 习惯。

参考文章
  • 1.概述

2. 为什么说「默认加载包不等于立刻吃满显存」?卸载时要注意什么?

题目

解释 AddPackage 后资源大致何时进内存;LoadAllAssetsRemovePackageunloadBundleByFGUI 各解决什么工程问题;为何不鼓励频繁装卸包。

深入解析
  • 延迟加载:正文写明 AddPackage 默认先加载描述,贴图、音频等往往用到才载入,利于控制首包体积与峰值内存。
  • 预热LoadAllAssets() 可在进关卡前主动拉齐包内资源,换的是内存与 IO 时间,要配合玩法节奏。
  • 卸载RemovePackage 会卸掉包内贴图等,基于该包创建的显示对象会失效;频繁装卸消耗 CPU、引发 GC,因此常规划常驻包关卡包
  • AB 托管:若 AB 由项目自建生命周期,可把 unloadBundleByFGUI 设为 false,避免 FGUI 在 RemovePackageUnload 和你的加载管线打架
答题示例

AddPackage 默认主要进描述,资源很多是按需载入的;LoadAllAssets 用来提前全装进内存。

RemovePackage 会卸资源,界面会花,不适合高频抖;AB 自己管就要关 unloadBundleByFGUI 或对接好Unload时机。

参考文章
  • 8.加载包

3. FairyGUI 里嵌 Spine / 龙骨,着色器和预乘设置不对会怎样?Unity 还要做什么宏?

题目

DefaultFGUI/Image 两类着色器在遮罩、预乘上的取舍;「贴图是否已预乘」为什么要与导出一致;FAIRYGUI_SPINE / FAIRYGUI_DRAGONBONES 起什么作用。

深入解析
  • Default:骨骼运行时自带着色路线;要遮罩时,常规矩形遮罩往往裁不断骨骼,需按文档走自定义遮罩等方案。
  • FGUI/Image:更贴 FGUI 常规贴图管线,矩形遮罩能裁;但若贴图是 预乘 Alpha 而着色器未按预乘走,会出现边缘发白/发色不对
  • 预乘开关:必须和 Spine / DragonBones 导出选项对齐,否则颜色空间不一致再怎么调 Tint 都别扭。
  • 脚本宏:Unity 侧在 Player Settings → Scripting Define Symbols 增加 FAIRYGUI_SPINEFAIRYGUI_DRAGONBONES,编译进 FairyGUI 与对应运行时的桥接代码;龙骨流程还常伴随 Unity Data 生成步骤。
答题示例

Default 和 FGUI/Image 差在遮罩和预乘处理,预乘要和导出的图一致,不对就会假亮或假边。

Unity 要加 FAIRYGUI_SPINE 或 FAIRYGUI_DRAGONBONES 宏,龙骨还要按文档建 Unity Data。

参考文章
  • 17.Spine和DragonBones骨骼动画

4. GTextField、GRichTextField、GTextInput 有什么区别?什么时候用哪一个?

题目

从「是否支持交互」「是否支持图文混排」「是否支持输入」三个维度对比三种文本控件,并给出典型使用场景。

深入解析
  • GTextField(普通文本):纯显示控件,不支持交互、超链接、图文混排、HTML;支持 UBB 样式标签([color][size][b] 等),但不支持 [img][url]。适合标题、数值、固定说明文字等只读场景
  • GRichTextField(富文本):在普通文本基础上增加交互能力超链接图文混排HTML 语法支持;UBB 扩展了 [img][url] 标签。适合聊天内容、带链接的说明、需要内嵌图片的文本。
  • GTextInput(输入文本):专门用于用户输入,支持单行、多行、密码模式、输入限制等;可通过 onChanged 监听内容变化,onSubmit 监听回车提交。适合登录框、搜索框、聊天输入框等可编辑场景

选用口诀:只读用普通,要交互或图文混排用富文本,要输入用输入文本。

答题示例

普通文本只显示,不能点、不能混排;富文本支持超链接、图文混排和交互;输入文本专门做用户输入。

标题、数值用普通文本;聊天内容、带链接的说明用富文本;登录框、搜索框用输入文本。

参考文章
  • 20.FGUI基础-控件-文本-普通文本
  • 22.FGUI基础-控件-文本-富文本
  • 23.FGUI基础-控件-文本-输入文本

5. GList 的虚拟列表是什么?开启虚拟列表要满足哪些前提?

题目

解释虚拟列表解决什么问题;SetVirtual()SetVirtualAndLoop() 的区别;开启虚拟列表前必须配置哪些内容。

深入解析
  • 解决的问题:当列表数据量很大(如几百上千条)时,如果为每条数据都创建一个显示对象,内存和 DrawCall 会爆炸。虚拟列表只渲染可见区域内的 item,滚动时复用这些对象,大幅降低内存和渲染压力。
  • API 区别
    • SetVirtual():普通虚拟列表,滚动到边界停止。
    • SetVirtualAndLoop():循环虚拟列表,滚动到末尾会从头继续,只支持单行或单列布局
  • 前提条件
    1. 必须定义 itemRenderer 回调(list.itemRenderer = RenderListItem)。
    2. 必须开启滚动(组件溢出设为滚动)。
    3. 必须设置项目资源(item 的模板)。
    4. 设置 list.numItems 触发渲染。
  • 对象池配合:虚拟列表内部会使用对象池,AddItemFromPoolRemoveChildToPool 等 API 在非虚拟模式下也适用。
答题示例

虚拟列表只渲染可见区域,滚动时复用对象,解决大数据量列表的内存和性能问题。

开启前要设 itemRenderer 回调、开滚动、设 item 模板、设 numItems;循环列表还要单行或单列布局。

参考文章
  • 34.FGUI基础-控件-列表

6. Controller 控制器如何实现组件的多状态切换?属性控制有哪些类型?

题目

说明控制器在 FairyGUI 中的角色;列举至少四种属性控制类型及其作用;selectedIndexSetSelectedIndex 的区别是什么。

深入解析
  • 角色定位:控制器为组件添加多状态切换能力,是实现分页、按钮状态、属性变化等交互的核心机制。一个组件可以有多个控制器,每个控制器管理一组状态(页面)。
  • 属性控制类型
控制类型 作用 支持缓动
显示控制 不同页面显示/隐藏不同元件
位置控制 不同页面元件在不同坐标
大小控制 不同页面不同宽高/Scale
颜色控制 不同页面不同颜色(图片/文本/装载器)
外观控制 不同页面不同透明度/变灰/旋转/不可触摸 部分
文本控制 不同页面不同文本内容
图标控制 不同页面不同图标 URL
动画控制 不同页面不同播放状态/帧
  • API 区别
    • selectedIndex:设置当前页面索引,会触发 onChanged 事件。
    • SetSelectedIndex(index):切换页面但不触发事件,适合初始化或程序内部切换。
    • selectedPage:按页面名称切换,更直观但依赖命名一致性。
  • 缓动控制GearBase.disableAllTweenEffect = true 可全局关闭属性变化的缓动效果。
答题示例

控制器让组件能切换多套状态,比如按钮的 normal/over/down/selected,或者分页容器的不同页。

属性控制包括显示、位置、大小、颜色、外观、文本、图标、动画等,位置和大小支持缓动。

selectedIndex 会触发事件,SetSelectedIndex 不触发,适合静默切换。

参考文章
  • 25.FGUI基础-控件-控制器

7. FairyGUI 的事件冒泡机制是怎样的?如何阻止事件传播?

题目

说明 FairyGUI 事件从触发到处理的传播路径;StopPropagationCaptureTouch 各解决什么问题;EventContext 中 senderinitiator 有什么区别。

深入解析
  • 冒泡机制:事件从目标元件开始,逐级向上传播到父级组件,直到 GRoot。这意味着父组件可以监听子组件的事件,但子组件无法阻止父组件收到事件(除非主动停止)。
  • StopPropagation:在事件处理中调用 context.StopPropagation(),阻止事件继续向上冒泡。常用于「点击内部按钮不触发外层面板的关闭」这类场景。
  • CaptureTouch:调用后,即使手指移出元件范围,仍能收到后续的 TouchMoveTouchEnd 事件。典型场景是拖拽:按住按钮开始拖动后,手指滑出按钮区域仍要跟踪。
  • sender vs initiator
    • sender:事件绑定的目标元件,即 onClick.Add() 时绑定的那个对象。
    • initiator:实际触发事件的元件,可能是 sender 的子元件。
btn.onClick.Add((EventContext context) => {
    Debug.Log($"sender: {context.sender}");
    Debug.Log($"initiator: {context.initiator}");
    context.StopPropagation(); // 阻止冒泡
});
答题示例

事件从目标元件向上冒泡到 GRoot;StopPropagation 阻止继续传播,CaptureTouch 让触摸事件即使手指移出也能跟踪。

sender 是绑定事件的对象,initiator 是实际触发的对象,两者可能不同。

参考文章
  • 40.FGUI基础-Unity中的使用必备-事件机制

8. FairyGUI 的 DrawCall 优化有哪些关键手段?

题目

说明 fairyBatching 的作用和适用场景;哪些操作会破坏合批;InvalidateBatchingState 什么时候需要调用。

深入解析
  • fairyBatching:开启后 FGUI 会尝试将同一图集、同一层级的元素合并为一个 DrawCall。适用于静态或变化较少的 UI 面板。
  • 破坏合批的因素
    • 不同图集的元素穿插排列。
    • 动态改变元素层级或显示/隐藏。
    • 使用遮罩、裁剪等需要 Stencil 的功能。
    • 插入 3D 对象或粒子(GoWrapper)。
  • InvalidateBatchingState:手动触发深度重算。当动态改变 UI 结构后(如显示/隐藏大量元素、改变层级),调用此方法让 FGUI 重新规划渲染顺序。
  • 优化建议
    • 同一图集的元素尽量相邻摆放。
    • 避免频繁改变 UI 结构。
    • 合理规划图集,减少材质切换。
    • 静态面板开 fairyBatching,动态面板慎用或配合手动刷新。
答题示例

fairyBatching 开启后尝试合并同图集同层级的元素,减少 DrawCall。

不同图集穿插、遮罩、动态改层级都会破坏合批;结构变化后要调 InvalidateBatchingState 重算。

优化关键是同图集元素相邻、少动结构、合理规划图集。

参考文章
  • 43.FGUI基础-Unity中的使用必备-DrawCall优化


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏