53.总结
53.1 知识点

学习的主要内容

必须达到的水平

学会举一反三

FairyGUI相对其它UI的优势

53.2 核心要点速览
FairyGUI 是什么
- 跨引擎的开源 UI 方案:不是某一个引擎插件的名字那么简单,而是一套「独立编辑器 + 各引擎运行时库」的组合。
- 编辑器负责可视化拼装、动效与资源组织;运行时以各引擎 SDK 的形式存在,解析编辑器导出的数据并在游戏里绘制、响应输入。
- 公开资料里常提到支持的引擎除 Unity 外,还包括 Unreal、Cocos2dx、Egret、LayaAir、Flash 等;跨引擎是特点,也意味着「不是所有引擎分支都同等成熟」——后面谈缺点会回到这一点。
从编辑器到游戏里看见界面
工程上可以记成一条顺序很硬的流水线,后面各篇都是在填这条线上的细节:
- 在 FairyGUI 编辑器里把界面搭好,完成结构摆放与资源引用。
- 发布 / 导出:得到
图集(Atlas)和描述 UI 结构的配置文件等运行时真正要读的资源。 - 把资源放进 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 Store 搜 FairyGUI 装 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 常用 Bilinear;Max 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好。 - 动态建 UIPanel:
AddPackage→GameObject设 UI 层 →AddComponent<UIPanel>→ 填包名/组件名 → 调CreateUI();渲染模式、Fairy Batching、排序等多从container和面板 API 走。 - SortingOrder 在 Screen Space 下 1000 像条「分水岭」,和 Unity 传统 2D UI 谁压谁有关;World Space 想按 Z 排要配合
SortWorldSpacePanelsByZOrder,但飘字、血条这类通常仍建议Screen Space + 坐标换算,别硬上 World Space 自找排序麻烦。 - 代码直创 UI:
SetContentScaleFactor(或等价组件)→AddPackage→ 补依赖包 →CreateObject/CreateObjectAsync→GRoot.inst.AddChild;销毁走Dispose。项目一大,纯 UIPanel 堆场景很难维护,动态创建更适合接 MVC / UI 栈等套路;正文提醒:动态创建的 FGUI 树别和别的 GameObject 强耦合。
StageCamera、UIContentScaler、UIConfig
- StageCamera 就是 UI 相机;首次动态创建 UI 或建 UIPanel 时常自动生成一份,也可手动 FairyGUI → UI Camera。上面 UICamera 的 Constant Size 管粒子等是否跟屏幕缩放,手机 / PC 取向不同。
- UIContentScaler 与
GRoot.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回收;resourceURL、packageItem等在承载资源的元件上才有意义。
GImage 与贴图资源
GImage:定位是简洁、静态:不能像装载器那样日常换url,默认也不可点击;需要切图或点击请用GLoader。- 资源库内可配置九宫格、平铺、平滑、纹理集归属(默认打包 / 单独一张 / 指定集编号等)、边缘像素重复(防平铺裂缝)、是否允许发布时剪透明边等。
- 填充裁剪与发布选项里的「裁剪图片边缘空白」可能打架——需要特殊填充时,常在图片属性里勾选禁止裁剪边缘空白,否则位移会怪。
- 翻转走渲染路径,不等同于把
scale设为 -1;个别非 Unity 分支的实现仍可能用scale模拟,避免混用两套翻转手段。 - Unity 里
view.GetChild("...").asImage,常用fillAmount、fillMethod,或texture = new NTexture(sprite)喂引擎贴图;动态CreateObject出图片时记得资源在库里已导出。 - 多倍图:例如
a.png与a@2x.png一起发布,并在发布设置里勾好对应后缀,运行时按缩放系数选用高清档,一般不必手写切换表。
GGraph 图形
- 支持空白、矩形、椭圆、正多边形、可编辑多边形等;典型用途:遮罩、占位、雷达图、箭头轮廓等矢量示意。
DrawRect、DrawEllipse等 API 重绘会盖住之前的形状;脚本里new GGraph()再DrawXXX后AddChild很常见的拼接方式。- 空白图形侧可走
SetNativeObject把 Unity 侧对象嵌进 FGUI(与后续专题衔接)。
GMovieClip 序列帧
- 动画素材在工程里落成 jta;来源可以是 Flash/Animate 导 plist、eas + 贴图拖入、编辑器里组序列、或 GIF 直接拖入转换。
- 时间轴侧:帧频、间隔帧、循环间隔、单帧停留、摆动播放(正播倒播往返);序列帧占用的所有格图必须在同一纹理集,因为不支持纹理分页——规划图集时要给动画留位。
- Unity:
asMovieClip;playing、frame;SetPlaySettings控制区间与循环;onPlayEnd做播放结束回调。
骨骼动画:Spine 与 DragonBones
- 当前支持范围按教材:Spine 3.8 导出、DragonBones 各版本导出;导入时只需骨骼描述文件(如
.json/.skel、.json/.dbbin),不必把骨骼当成普通单张 UI 图那条导入链硬套。 - 资源面板里可选着色器:Default(骨骼库默认;要遮罩可能走自定义遮罩思路)、FGUI/Image(可走常规矩形遮罩,但须和预乘匹配,否则颜色发灰/发边)。
- 贴图是否预乘必须与 DCC 导出设置一致,否则显示必偏。
- Unity 工程:安装对应 Spine / 龙骨 Unity 运行时,在 Scripting Define Symbols 增加
FAIRYGUI_SPINE或FAIRYGUI_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 API:
text、textFormat.size、textFormat.color、align、verticalAlign、singleLine等;动态创建用new GTextField()。
字体处理
| 字体类型 | 说明 | 注意事项 |
|---|---|---|
| 系统字体 | 不建议 | 跨设备字体名可能不存在,效果不可控 |
| TTF 字体 | 最常用 | 发布后字体文件不进包,需手动放 Unity 并注册 |
| 位图字体 | 特殊需求 | 用图片表示字符,支持 BMFont 导出的 fnt 文件 |
- TTF 字体注册:放
Resources或Resources/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(单行模式下回车确认)。 - API:
RequestFocus()主动获取焦点;SetSelection(0, 4)选中指定范围。
组、控制器与关联系统
GGroup 组
- 普通组:仅编辑时有效,辅助整体移动、调整深度、复制粘贴;发布后不存在。
- 高级组:发布后保留,可代码控制显隐、位置、布局。
- 布局模式:无(仅控制显隐)、水平布局、垂直布局;行列距、排除隐藏对象、禁用自动计算包围等。
- Unity API:
gGroup.visible、gGroup.layout;无法直接获取组内子对象,需遍历view.numChildren判断GetChildAt(i).group == gGroup。
Controller 控制器
- 核心作用:为组件添加多状态切换能力,实现分页、按钮状态、属性变化等。
- 创建:组件内可建多个控制器;控制器名不要重名;页面索引从 0 开始。
- 属性控制类型:
| 控制类型 | 说明 | 支持缓动 |
|---|---|---|
| 显示控制 | 指定页面显示/隐藏元件 | 否 |
| 位置控制 | 不同页面不同 XY 坐标 | 是 |
| 大小控制 | 不同页面不同宽高/Scale | 是 |
| 颜色控制 | 不同页面不同颜色(图片/文本/装载器) | 是 |
| 外观控制 | 不同页面不同透明度/变灰/旋转/不可触摸 | 部分 |
| 文本控制 | 不同页面不同文本内容 | 否 |
| 图标控制 | 不同页面不同图标 URL | 否 |
| 动画控制 | 不同页面不同播放状态/帧 | 否 |
| 字体大小控制 | 不同页面不同字号 | 否 |
- Unity API:
selectedIndex(切换页面,触发事件)、SetSelectedIndex(不触发事件)、selectedPage(按名字切换)、onChanged监听切换;GearBase.disableAllTweenEffect = true关闭所有缓动。 - 联动:按钮可绑定控制器,点击时自动切换控制器页面。
关联系统
- 定位:FairyGUI 自动布局核心,类似 UGUI 锚点但更灵活——可定义任意两个元件之间的关系。
- 关联类型:横向(左左、左右、右左、右右、宽度百分比等)、纵向(顶顶、顶底、底顶、底底、高度百分比等)。
- 关键点:关联只在目标元件位置/大小变化时生效;设置关联不等于居中/对齐,初始位置仍需手动设置。
- Unity API:
AddRelation(target, RelationType.Left_Left)添加关联;RemoveRelation删除某种关联;relations.ClearAll()清空所有关联;relations.ClearFor(target)清空与指定对象的所有关联。
标签与按钮
GLabel 标签
- 本质:组合控件,至少包含 title(文本)和 icon(图片)两个元件。
- 创建方式:自动创建(菜单 → 资源 → 新建标签);手动创建需新建组件并设扩展为标签,内部元件命名必须为
title和icon。 - Unity API:
text、icon、titleColor、titleFontSize;不转成 GLabel 也能直接用 GObject 的 text/icon 属性。
GButton 按钮
- 三种模式:普通按钮(无状态)、单选按钮(选中后保持)、复选按钮(可切换选中状态)。
- 命名规则:控制器名 button、文本 title、图片 icon。
- 设计属性:
- 声音:点击音效,可全局设置
UIConfig.buttonSound。 - 按下效果:缩放(改 Scale,轴心自动设为 0.5,0.5)、变暗(改所有图片颜色)。
- 声音:点击音效,可全局设置
- 实例属性:
selected(选中状态)、text、icon、选中时标题/图标。 - Unity API:
selected:获取/设置选中状态。onClick:点击事件;FireClick(true, true)模拟点击(第一个参数是否触发效果,第二个是否触发事件)。onChanged:状态变化事件(单选/复选按钮常用)。
- 音效控制:
GRoot.inst.EnableSound()/DisableSound()开关音效;GRoot.inst.soundVolume调整音量。
进度条、滑动条与滚动条
GProgressBar 进度条
- 原理:按进度改变元件宽度、高度或填充比例。
- 关键元件:
bar(横向,改变宽度)、bar_v(纵向,改变高度)、title(显示进度文本)、ani(序列帧动画,帧索引对应进度值)。 - 标题类型:百分比、当前值/最大值、当前值、最大值。
- 反向:进度条延伸方向相反。
- Unity API:
value当前值;TweenValue(targetValue, duration)缓动到目标值。 - 关联增强:可在进度条内放一个元素与 bar 建立关联,实现进度变化时元素跟随移动的效果。
GSlider 滑动条
- 与进度条的区别:增加可拖动的滑块按钮(grip),允许玩家手动改变值。
- 关键元件:
bar、bar_v、title、grip(拖动按钮);grip 需与 bar 建立关联。 - 设计属性:
wholeNumbers(整数输入)、changeOnClick(点击滑动条改变值)。 - Unity API:
value、onChanged监听值变化。
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 = RenderListItem;list.numItems = 30会自动创建对象并调用回调初始化。 - 虚拟列表:
SetVirtual()开启,只渲染可见区域的 item,适合大数据量;前提是必须定义 itemRenderer、开启滚动、设置项目资源。 - 循环列表:
SetVirtualAndLoop(),只支持单行或单列布局。 - 事件:
onClickItem点击 item。
GComboBox 下拉框
- 组成:下拉框主体 + 弹出组件 + 下拉框 Item。
- 弹出组件构成:背景图 + 垂直滚动列表(命名为
list)。 - 属性:可见项目数、弹出方向(建议自动)、选择控制(绑定控制器联动)。
- Unity API:
items、icons、values:代码初始化选项内容。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.Width、RelationType.Height。
坐标系统
坐标转换 API
| 方法 | 作用 |
|---|---|
LocalToGlobal |
局部坐标 → 屏幕坐标 |
GlobalToLocal |
屏幕坐标 → 局部坐标 |
LocalToRoot |
局部坐标 → GRoot 坐标 |
RootToLocal |
GRoot 坐标 → 局部坐标 |
TransformPoint |
任意两个组件间坐标转换 |
- GRoot:UI 的根容器,所有动态创建的 UI 都挂在其下;坐标原点在左上角。
- 屏幕坐标:Unity 屏幕空间坐标,Y 轴向下;与 Unity 世界坐标(Y 轴向上)不同。
输入处理
触摸检测
- Stage.isTouchOnUI:判断当前触摸是否落在 UI 上,常用于区分「点 UI」和「点 3D 场景」。
- InputEvent:封装触摸位置、按钮状态、滚轮等信息。
手势识别
- FairyGUI 内置常见手势:点击、双击、长按、滑动、缩放、旋转。
- 手势通过
onClick、onRightClick、onTouchBegin/End/Move等事件实现;复杂手势可结合时间与位移判断。
键盘输入
Stage.GetTouch、Stage.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_cn、assets_en。 - 资源映射:同一资源名在不同分支下可以有不同内容,运行时按分支自动切换。
控制器联动
- 控制器页面名可与分支名对应,实现「切换控制器 = 切换分支资源」的效果。
多国语言
字符串管理
- 导出字符串:编辑器导出多语言文本表(XML 或 JSON 格式)。
- 翻译流程:导出 → 翻译 → 导入;支持增量更新。
- SetStringsSource:运行时加载翻译后的字符串表,
UIPackage.SetStringsSource(xml)。
动态文本
- 文本模板:
{count=100}声明参数,运行时SetVar("count", "200").FlushVars()替换。 - 适合数值变化频繁的文本,如「剩余 {count} 次」。
树控件
GTree 与 GTreeNode
- GTree:继承自 GList,专门用于树形结构展示。
- GTreeNode:树节点,包含
data、expanded、parent等属性。 - 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:显示/隐藏窗口。
弹出功能
Popup 与 ContextMenu
- 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 的资源,必须先
AddPackageB(或通过dependencies枚举再加载),否则显示异常。 - 导出:跨包引用的资源须标导出(缩略图小红点);需要代码
CreateObject的组件一般也要能对外导出,否则访问不到。 - URL:
ui://包名/资源名,不含文件夹路径,因此同一包内资源名冲突会直接乱套。
答题示例
包在工程里是一个目录,发布出去是描述文件加图集;package.xml 是包的索引。
跨包用资源要先加载被依赖包,导出要打红点;地址用 ui://包名/资源名,所以包内资源名要唯一。
参考文章
- 5.包的概念
- 8.加载包
3. GImage 和 GLoader 什么时候用哪一个?
题目
各解决什么问题;为什么「不动态换图、不要点击」的底图更适合 GImage;要点点击或换头像时该怎么选。
深入解析
GImage:为静态显示优化,不能像装载器那样日常改url,默认也不参与点击——适合背景、固定图标等资源在编辑期就定死的元素。GLoader:核心是动态url,可指向包内ui://资源,也可按工程约定指向 Resources 等;可装图片、序列帧、子组件;需要运行时换皮、换图标、列表项模板时首选。- 性能直觉:能用纯图片解决的别硬上装载器;但一旦需求里有「同一格子换不同图」,装载器比反复
CreateObject图片更贴合设计。
答题示例
GImage 适合不变的图,不能动态换资源,默认也不可点。
GLoader 用 url 动态换图、动画或组件,要点击或热更资源时用装载器。
参考文章
- 14.GImage图片
- 18.GLoader装载器
进阶题
1. 从「在编辑器里画完界面」到「Unity 里跑起来」,中间最关键的三步是什么?产物分别是啥?
题目
按时间顺序说出 FairyGUI 的典型工作流,并说明导出侧主要交付给程序的资源形态。
深入解析
- 编辑:在 FairyGUI 编辑器中完成 UI 结构与资源配置(包、组件、面板等资源组织方式由工程约定)。
- 导出:生成 图集(减少绘制批次的贴图打包结果)和 配置文件(描述界面树、控制器、关联等的数据;具体扩展名与发布选项以项目与版本为准)。
- 引擎接入:把资源导入 Unity,挂载/初始化 FairyGUI 运行环境(常见做法是挂载
UIPanel、按路径加载包、用UIConfig等对全局行为做一次性配置),再用脚本驱动逻辑。
踩坑提示:新人常只记得「拖 Prefab」,但在 FGUI 体系里要先建立「包是否加载、默认资源路径、缩放策略是否正确」的直觉,否则界面空白往往不是 C# 写错一行,而是资源管线没接通。
答题示例
先在 FairyGUI 编辑器做界面,再导出图集和配置文件进 Unity,最后用 FairyGUI 的 SDK 加载包并写脚本逻辑。
程序最关心的是包有没有按路径加载成功、导出设置是否与运行时默认规则一致。
参考文章
- 1.概述
2. UIPackage.AddPackage 和挂在场景里的 UIPanel,各自在「谁能自动加载包」上有什么区别?
题目
对比 Resources 路径加载与 AssetBundle 加载时,重复加载行为有何不同;场景里配置的 UIPanel 对资源位置有什么硬性要求;动态创建 UI 前通常要完成哪几步。
深入解析
- Resources:
AddPackage(路径)以传入路径为 key 做去重,重复调一般无害。 - AssetBundle:
AddPackage(AB)不做排重,同一 AB 多次加载要自己防。 - UIPanel:Inspector 里选包、选组件很省事,但文档明确:只会自动载入放在 Resources(含子目录)下的包;AB 方案必须先代码
AddPackage。 - 动态流程:先
SetContentScaleFactor(或组件等价配置)确定逻辑分辨率策略 →AddPackage主包 → 遍历dependencies补依赖 →CreateObject/ 异步版本 →GRoot.inst.AddChild;销毁用Dispose,别跟 UnityDestroy混用惯例。
答题示例
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 后资源大致何时进内存;LoadAllAssets、RemovePackage、unloadBundleByFGUI 各解决什么工程问题;为何不鼓励频繁装卸包。
深入解析
- 延迟加载:正文写明
AddPackage默认先加载描述,贴图、音频等往往用到才载入,利于控制首包体积与峰值内存。 - 预热:
LoadAllAssets()可在进关卡前主动拉齐包内资源,换的是内存与 IO 时间,要配合玩法节奏。 - 卸载:
RemovePackage会卸掉包内贴图等,基于该包创建的显示对象会失效;频繁装卸消耗 CPU、引发 GC,因此常规划常驻包与关卡包。 - AB 托管:若 AB 由项目自建生命周期,可把
unloadBundleByFGUI设为 false,避免 FGUI 在RemovePackage时Unload和你的加载管线打架。
答题示例
AddPackage 默认主要进描述,资源很多是按需载入的;LoadAllAssets 用来提前全装进内存。
RemovePackage 会卸资源,界面会花,不适合高频抖;AB 自己管就要关 unloadBundleByFGUI 或对接好Unload时机。
参考文章
- 8.加载包
3. FairyGUI 里嵌 Spine / 龙骨,着色器和预乘设置不对会怎样?Unity 还要做什么宏?
题目
Default 与 FGUI/Image 两类着色器在遮罩、预乘上的取舍;「贴图是否已预乘」为什么要与导出一致;FAIRYGUI_SPINE / FAIRYGUI_DRAGONBONES 起什么作用。
深入解析
- Default:骨骼运行时自带着色路线;要遮罩时,常规矩形遮罩往往裁不断骨骼,需按文档走自定义遮罩等方案。
- FGUI/Image:更贴 FGUI 常规贴图管线,矩形遮罩能裁;但若贴图是 预乘 Alpha 而着色器未按预乘走,会出现边缘发白/发色不对。
- 预乘开关:必须和 Spine / DragonBones 导出选项对齐,否则颜色空间不一致再怎么调 Tint 都别扭。
- 脚本宏:Unity 侧在 Player Settings → Scripting Define Symbols 增加
FAIRYGUI_SPINE或FAIRYGUI_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():循环虚拟列表,滚动到末尾会从头继续,只支持单行或单列布局。
- 前提条件:
- 必须定义
itemRenderer回调(list.itemRenderer = RenderListItem)。 - 必须开启滚动(组件溢出设为滚动)。
- 必须设置项目资源(item 的模板)。
- 设置
list.numItems触发渲染。
- 必须定义
- 对象池配合:虚拟列表内部会使用对象池,
AddItemFromPool、RemoveChildToPool等 API 在非虚拟模式下也适用。
答题示例
虚拟列表只渲染可见区域,滚动时复用对象,解决大数据量列表的内存和性能问题。
开启前要设 itemRenderer 回调、开滚动、设 item 模板、设 numItems;循环列表还要单行或单列布局。
参考文章
- 34.FGUI基础-控件-列表
6. Controller 控制器如何实现组件的多状态切换?属性控制有哪些类型?
题目
说明控制器在 FairyGUI 中的角色;列举至少四种属性控制类型及其作用;selectedIndex 和 SetSelectedIndex 的区别是什么。
深入解析
- 角色定位:控制器为组件添加多状态切换能力,是实现分页、按钮状态、属性变化等交互的核心机制。一个组件可以有多个控制器,每个控制器管理一组状态(页面)。
- 属性控制类型:
| 控制类型 | 作用 | 支持缓动 |
|---|---|---|
| 显示控制 | 不同页面显示/隐藏不同元件 | 否 |
| 位置控制 | 不同页面元件在不同坐标 | 是 |
| 大小控制 | 不同页面不同宽高/Scale | 是 |
| 颜色控制 | 不同页面不同颜色(图片/文本/装载器) | 是 |
| 外观控制 | 不同页面不同透明度/变灰/旋转/不可触摸 | 部分 |
| 文本控制 | 不同页面不同文本内容 | 否 |
| 图标控制 | 不同页面不同图标 URL | 否 |
| 动画控制 | 不同页面不同播放状态/帧 | 否 |
- API 区别:
selectedIndex:设置当前页面索引,会触发onChanged事件。SetSelectedIndex(index):切换页面但不触发事件,适合初始化或程序内部切换。selectedPage:按页面名称切换,更直观但依赖命名一致性。
- 缓动控制:
GearBase.disableAllTweenEffect = true可全局关闭属性变化的缓动效果。
答题示例
控制器让组件能切换多套状态,比如按钮的 normal/over/down/selected,或者分页容器的不同页。
属性控制包括显示、位置、大小、颜色、外观、文本、图标、动画等,位置和大小支持缓动。
selectedIndex 会触发事件,SetSelectedIndex 不触发,适合静默切换。
参考文章
- 25.FGUI基础-控件-控制器
7. FairyGUI 的事件冒泡机制是怎样的?如何阻止事件传播?
题目
说明 FairyGUI 事件从触发到处理的传播路径;StopPropagation 和 CaptureTouch 各解决什么问题;EventContext 中 sender 和 initiator 有什么区别。
深入解析
- 冒泡机制:事件从目标元件开始,逐级向上传播到父级组件,直到 GRoot。这意味着父组件可以监听子组件的事件,但子组件无法阻止父组件收到事件(除非主动停止)。
- StopPropagation:在事件处理中调用
context.StopPropagation(),阻止事件继续向上冒泡。常用于「点击内部按钮不触发外层面板的关闭」这类场景。 - CaptureTouch:调用后,即使手指移出元件范围,仍能收到后续的
TouchMove、TouchEnd事件。典型场景是拖拽:按住按钮开始拖动后,手指滑出按钮区域仍要跟踪。 - 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