尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

告别手改Prefab:画布导出自动生成Unity/Godot/Cocos UI

告别手改Prefab:画布导出自动生成Unity/Godot/Cocos UI 1. 为什么我劝你别再手改 Prefab 了做游戏 UI 这行十来年我见过太多团队在同一个坑里反复摔跤美术在 Figma 或者 PS 里把界面调得漂漂亮亮程序拿到切图之后在 Unity、Godot、Cocos 里一个节点一个节点地摆摆完发现按钮位置偏了两像素又回去改 Prefab。改完 Prefab 之后策划说文案要换字号要调于是再改一遍。等到版本迭代到第三轮Prefab 里的层级已经乱成一锅粥谁也不敢动一动就崩。这个问题的根源不在于工具不好用而在于工作流的起点选错了。Prefab 是引擎里的运行时资产它天生就是给程序做逻辑挂载和状态管理用的不是给美术做视觉排版用的。你拿它当画布使就等于拿螺丝刀当锤子敲钉子能用但迟早出事。我最近在几个项目里推行了一套新流程把 UI 的视觉排版全部放在画布工具里完成通过导出中间格式再自动生成 Unity、Godot、Cocos 三个引擎的 UI 结构。核心思路一句话概括就是——画布负责“长什么样”引擎负责“怎么动”。Prefab 只保留逻辑脚本和动态绑定的部分静态布局全部由导出流程自动生成。这套方案解决的核心痛点有三个。第一跨引擎复用。现在很多团队同时要出 PC 版、移动版甚至还要上小游戏平台Unity 和 Cocos 两套 UI 各做一遍人力成本翻倍。第二美术与程序的职责边界。美术在画布里改完直接导出程序不需要重新摆节点只需要在生成的骨架上挂脚本。第三版本对比和回滚。画布文件是结构化的导出产物是文本化的Git diff 一眼就能看出改了哪里比在引擎里肉眼比对 Prefab 靠谱得多。适合读这篇内容的人如果你正在做 Unity、Godot 或 Cocos 的项目团队里有美术和程序协作做 UI 的环节或者你一个人兼着设计和开发两头跑那这套流程能帮你省下大量重复劳动。哪怕你只用其中一个引擎画布导出的思路同样适用因为它的本质是把“视觉”和“逻辑”解耦这个原则跟引擎无关。2. 整体设计思路画布到引擎的中间层怎么搭2.1 为什么选“画布导出”而不是“引擎内编辑”先说清楚一个概念。这里说的“画布”指的是任何能产出结构化 UI 描述的工具比如 Figma、Sketch、Adobe XD甚至你自己用 Web 技术搭的一个无限画布编辑器。关键不在于用哪个工具而在于这个工具能不能输出一份机器可读的布局描述。Unity 自带的 UI Builder 和 Godot 的编辑器其实也能做可视化排版但它们的问题在于绑定太深。你在 Unity 里摆好的 UI导出到 Godot 就得重来。而画布工具的输出是引擎无关的一份布局描述可以喂给三个不同的导出器分别生成.prefab、.tscn和.prefabCocos 的格式。我试过直接在 Unity 里用脚本批量生成 UI 节点也试过用 Godot 的编辑器脚本做类似的事。实测下来引擎内脚本生成的问题在于调试成本高。你改一行代码要等引擎编译、运行、看效果反馈循环太长。而在画布工具里美术改完立刻能看到视觉结果导出只是最后一步。另一个考量是协作效率。画布工具天生支持多人同时编辑评论、标注、版本历史都是现成的。引擎的 Prefab 虽然也能用 Git 管理但合并冲突处理起来非常痛苦尤其是两个人同时改同一个 UI 界面的时候。2.2 中间格式的设计原则中间格式是整个流程的枢纽它的设计直接决定了导出器好不好写、容不容易维护。我踩过的坑告诉我中间格式要满足几个硬性条件。第一必须是纯文本且结构扁平。JSON 是最省事的选择因为三种引擎的脚本都能轻松解析。不要用二进制格式否则 Git diff 没法看出了问题也不好排查。结构上尽量扁平避免过深的嵌套因为不同引擎对节点层级的处理方式不一样扁平结构更容易做映射。第二坐标系统一要统一。画布工具的坐标系原点通常在左上角Y 轴向下。Unity 的 UI 坐标系原点在中心Y 轴向上。Godot 的 Control 节点原点在左上角但锚点系统又是另一套逻辑。Cocos 的坐标系跟 Godot 类似。我的做法是在中间格式里统一用左上角原点、Y 轴向下导出器各自做转换。这样画布工具那边不需要做任何特殊处理转换逻辑全部收敛到导出器里。第三样式和布局分离。一个按钮的位置、大小属于布局信息它的颜色、圆角、字体属于样式信息。中间格式里要把这两类分开存因为布局信息在导出到不同引擎时转换规则不同而样式信息大部分可以直接映射。分开之后改样式不需要动布局改布局也不会影响样式。第四预留扩展字段。你不可能一开始就把所有引擎的所有特性都考虑到。中间格式里要留一个meta或者extra字段允许导出器往里塞引擎特有的属性。比如 Unity 的LayoutElement组件、Godot 的size_flags、Cocos 的Widget组件这些都可以通过扩展字段传递。2.3 三引擎的映射策略差异Unity、Godot、Cocos 的 UI 系统虽然都是基于节点树的但细节差异很大导出器不能一套逻辑走天下。Unity 的 UGUI 用RectTransform做布局锚点和轴心是核心概念。导出的时候如果画布里用的是绝对定位那RectTransform的锚点就设成左上角anchoredPosition直接填坐标。如果画布里用了自动布局那就要映射到HorizontalLayoutGroup或者VerticalLayoutGroup。我的经验是第一版导出器只支持绝对定位自动布局后面再补因为绝对定位的转换逻辑最简单出错概率最低。Godot 的 Control 节点用anchor_left、anchor_top、anchor_right、anchor_bottom四个值描述锚点再加上offset_left等四个偏移值。这套系统比 Unity 的更灵活但也更啰嗦。导出的时候如果画布节点是绝对定位就把四个锚点都设成 0偏移值填实际坐标。如果是相对定位就根据父节点的尺寸算出锚点比例。Cocos Creator 的 UI 系统跟 Unity 比较像也是UITransform加锚点的组合。但 Cocos 的Widget组件功能很强可以自动对齐父节点。导出的时候如果画布节点有对齐约束就生成对应的Widget配置。这里有个关键决策导出器要不要生成布局组件。我的建议是第一版全部用绝对定位不生成任何自动布局组件。因为自动布局的行为在不同引擎里差异太大而且一旦生成错了排查起来很麻烦。等绝对定位的流程跑通了再针对特定场景加自动布局支持。3. 核心细节解析从画布节点到引擎节点的映射规则3.1 节点类型映射表画布工具里的节点类型通常比较有限常见的有矩形、文本、图片、按钮、容器。引擎里的 UI 节点类型就丰富多了。下面这张表是我在实际项目中总结的映射关系覆盖了大部分常见场景。画布节点类型Unity 对应组件Godot 对应节点Cocos 对应组件矩形/容器RectTransform ImageControl ColorRectUITransform Sprite文本RectTransform TextMeshProControl LabelUITransform Label图片RectTransform ImageControl TextureRectUITransform Sprite按钮RectTransform Image ButtonControl ButtonUITransform Button滚动容器ScrollRect MaskScrollContainerScrollView输入框InputFieldLineEditEditBox这张表看起来简单但实际映射的时候有几个坑。第一个坑是文本组件。Unity 现在主推 TextMeshPro但老项目可能还在用Text。导出器要能根据配置切换。Godot 的Label和RichTextLabel也是两套东西前者不支持富文本后者支持但性能差一些。Cocos 的Label支持RichText模式但需要额外配置。第二个坑是图片的九宫格。画布工具里的图片通常有拉伸模式导出到引擎的时候要映射成九宫格Sliced或者平铺Tiled。Unity 的Image组件用Type字段控制Godot 的TextureRect用stretch_modeCocos 的Sprite用type。这三个的枚举值不一样导出器要做转换。第三个坑是按钮的交互区域。画布里的按钮可能只是一个视觉矩形但引擎里的按钮需要明确的点击区域。Unity 的Button组件依赖Graphic作为射线检测目标Godot 的Button自带点击区域Cocos 的Button需要指定target节点。导出的时候要确保每个按钮都有对应的可点击节点。3.2 坐标与尺寸的转换计算坐标转换是导出器里最容易出错的部分因为三个引擎的坐标系和单位都不一样。我拿一个实际例子来说明。假设画布里有一个按钮位置是(120, 80)尺寸是200 x 60父容器尺寸是1920 x 1080。画布坐标系原点在左上角Y 轴向下。导出到 Unity的时候RectTransform的锚点设成左上角(0, 1)轴心设成(0, 1)那么anchoredPosition的计算方式是anchoredPosition.x 120 anchoredPosition.y -80注意 Y 轴要取负因为 Unity 的 Y 轴向上而画布的 Y 轴向下。尺寸直接填sizeDelta (200, 60)。导出到 Godot的时候Control节点的锚点全部设成 0偏移值这样算offset_left 120 offset_top 80 offset_right 120 200 320 offset_bottom 80 60 140Godot 的 Y 轴向下跟画布一致所以不需要取负。导出到 Cocos的时候UITransform的锚点设成(0, 1)位置这样算position.x 120 200 * 0.5 220 position.y -(80 60 * 0.5) -110Cocos 的position是相对于锚点的而且 Y 轴向上所以计算方式又不一样。这三个转换逻辑我写了三遍才跑通每次都是因为某个轴向搞反了导致 UI 跑到屏幕外面。建议在导出器里加一个坐标校验步骤把转换后的坐标反算回画布坐标系跟原始值对比误差超过 1 像素就报警。3.3 样式属性的映射与降级样式映射的复杂度取决于画布工具支持多少种样式属性。Figma 的样式系统非常丰富有填充、描边、阴影、模糊、渐变、混合模式等等。但引擎的 UI 系统支持程度参差不齐。我的策略是分级映射。把样式属性分成三档直接映射颜色、透明度、圆角、字体大小、字体颜色这些三个引擎都支持直接转就行。近似映射阴影、描边Unity 的 UGUI 原生不支持描边需要额外组件或者用图片代替。Godot 的Label支持描边但Control不支持。Cocos 的Label支持描边。遇到不支持的情况导出器要么生成额外的装饰节点要么在日志里警告。不支持映射模糊、混合模式、复杂渐变这些在 UI 层面基本没法还原导出器直接忽略但在日志里记录提醒美术这些效果需要程序单独处理。这里有个经验不要试图在导出器里做像素级还原。画布工具和引擎的渲染管线完全不同追求 100% 一致是徒劳的。导出器的目标是结构和布局一致样式做到 90% 接近就行剩下的细节让美术在引擎里微调。3.4 字体与多语言处理字体是 UI 导出里最容易被忽视的环节。画布里用的字体引擎里不一定有。尤其是中文字体文件体积大不可能每个项目都打包一份。我的做法是在中间格式里只存字体标识不存字体文件。导出器根据标识去查一个字体映射表这个表由项目配置。比如画布里用InterUnity 项目里映射到Assets/Fonts/Inter SDFGodot 项目里映射到res://fonts/inter.ttfCocos 项目里映射到resources/fonts/inter。多语言的处理更复杂。如果画布里的文本是写死的那导出之后就是静态文本切换语言需要重新导出。更好的做法是在画布里用占位符比如{title}、{description}导出器把这些占位符转成引擎的本地化键。Unity 用LocalizeStringEventGodot 用tr()Cocos 用i18n组件。注意如果项目有多语言需求画布里的文本节点一定要用占位符不要写死文案。否则每次改文案都要重新导出流程就失去意义了。4. 实操过程从零搭建一套导出流水线4.1 画布侧的准备与规范约定在开始写导出器之前画布侧要先定好规范。这一步不做后面导出器写得再漂亮也没用。命名规范是第一条。画布里的节点名称要能反映它的用途比如btn_start、txt_title、img_background。导出器根据前缀判断节点类型btn_开头的是按钮txt_开头的是文本img_开头的是图片pnl_开头的是容器。这样导出器不需要额外的类型标注直接从命名就能推断。层级规范是第二条。画布里的节点层级要尽量扁平避免超过三层的嵌套。因为引擎的 UI 层级太深会影响性能而且导出器的递归逻辑也容易出错。如果画布里的层级确实很深导出器可以在生成的时候做扁平化处理把中间的空容器去掉。组件规范是第三条。画布工具通常支持组件Component或者符号Symbol用来复用 UI 元素。导出器要能识别这些复用结构在引擎里生成对应的 Prefab 或者场景。Unity 用嵌套 PrefabGodot 用PackedSceneCocos 用嵌套 Prefab。这个功能比较复杂建议第一版先不支持等基础流程跑通了再加。导出标记是第四条。不是画布里的所有节点都需要导出到引擎。比如美术用来做参考的辅助线、标注、隐藏图层这些不应该出现在最终产物里。我的做法是在画布节点上加一个自定义属性export: true/false导出器只处理export: true的节点。4.2 导出器的核心代码结构导出器本身就是一个脚本输入是画布工具导出的 JSON输出是引擎的 UI 文件。我用 Python 写了一个原型因为 JSON 处理方便而且三种引擎的文件格式都是文本用模板引擎生成就行。核心结构分四层解析层读取画布 JSON构建一棵内部节点树。这一层负责处理画布工具特有的数据结构把不同工具的格式统一成内部格式。转换层遍历内部节点树把画布节点转换成引擎节点。这一层包含坐标转换、样式映射、类型映射的逻辑。生成层把引擎节点树序列化成目标文件格式。Unity 的.prefab是 YAMLGodot 的.tscn是自定义文本格式Cocos 的.prefab是 JSON。校验层检查生成的文件有没有明显错误比如坐标越界、字体缺失、图片路径不存在。解析层的代码大概长这样def parse_canvas_node(node): result { id: node[id], name: node[name], type: infer_type(node[name]), x: node[absoluteBoundingBox][x], y: node[absoluteBoundingBox][y], width: node[absoluteBoundingBox][width], height: node[absoluteBoundingBox][height], children: [], style: extract_style(node), export: node.get(export, True) } for child in node.get(children, []): result[children].append(parse_canvas_node(child)) return result转换层的核心是坐标转换函数前面已经讲过计算方式这里不重复。生成层用 Jinja2 模板每种引擎一套模板。校验层最简单遍历节点树检查坐标是否在父容器范围内字体标识是否在映射表里。4.3 Unity 导出器的关键实现Unity 的.prefab文件是 YAML 格式结构比较固定。一个典型的 UI Prefab 包含GameObject、RectTransform、CanvasRenderer、Image或TextMeshProUGUI等组件。导出器生成的时候要注意几个细节。第一文件头部的%YAML和%TAG不能少否则 Unity 识别不了。第二每个组件的fileID要唯一我用的方案是递增整数从 100000 开始每生成一个组件加 1。第三m_Children的顺序要和节点树的顺序一致否则 UI 的渲染层级会乱。Unity 的RectTransform有几个关键字段m_AnchorMin、m_AnchorMax、m_AnchoredPosition、m_SizeDelta、m_Pivot。绝对定位的情况下m_AnchorMin和m_AnchorMax都设成(0, 1)m_Pivot设成(0, 1)m_AnchoredPosition填转换后的坐标m_SizeDelta填尺寸。文本节点用TextMeshProUGUI组件关键字段是m_text、m_fontSize、m_fontColor、m_fontAsset。字体资源要提前在 Unity 项目里创建好导出器只填引用路径。提示Unity 的 Prefab 文件里组件的引用是通过fileID和guid定位的。字体、图片这些外部资源导出器要填正确的guid否则 Prefab 打开之后资源引用会丢失。建议在项目里维护一个资源映射表记录每个资源的guid。4.4 Godot 导出器的关键实现Godot 的.tscn文件格式比 Unity 的 YAML 简洁很多结构是[node]块加属性列表。一个典型的 Control 节点长这样[node nameButton typeButton parent.] offset_left 120.0 offset_top 80.0 offset_right 320.0 offset_bottom 140.0 text Start导出器生成的时候要注意节点的parent属性。根节点的parent是.子节点的parent是父节点的路径。路径用NodePath格式比如Panel/Button。Godot 的锚点系统比较特殊anchor_left、anchor_top、anchor_right、anchor_bottom四个值默认都是 0表示绝对定位。如果要做相对定位就把锚点设成 0 到 1 之间的比例值。第一版导出器全部用绝对定位锚点保持默认。文本节点用Label关键属性是text、theme_override_font_sizes/font_size、theme_override_colors/font_color。Godot 的字体资源用theme_override_fonts/font引用路径格式是res://fonts/inter.ttf。Godot 有个坑.tscn文件里的资源引用要用ExtResource和SubResource声明。如果导出器直接填路径字符串Godot 打开场景的时候会报错。正确的做法是在文件头部声明资源然后在节点属性里引用ExtResource的 ID。4.5 Cocos 导出器的关键实现Cocos Creator 的.prefab文件是 JSON 格式结构比 Unity 和 Godot 都简单。一个典型的节点对象包含__type__、_name、_children、_components等字段。导出器生成的时候要注意组件的__type__字段。Cocos 的组件类型用字符串标识比如cc.UITransform、cc.Sprite、cc.Label、cc.Button。每个组件的属性字段名跟编辑器里看到的一致但有些字段是内部使用的不能乱填。Cocos 的UITransform组件有_anchorPoint、_contentSize、_position三个关键字段。_anchorPoint是(0.5, 0.5)表示中心锚点(0, 1)表示左上角。_contentSize是{width, height}。_position是{x, y, z}注意 Cocos 的 Y 轴向上所以计算方式跟 Unity 类似。Cocos 的Label组件有_string、_fontSize、_color、_font等字段。字体资源用 UUID 引用导出器要填正确的 UUID。这个 UUID 可以在 Cocos 项目的.meta文件里找到。注意Cocos Creator 的版本差异比较大2.x 和 3.x 的 Prefab 格式完全不同。导出器要明确目标版本不要试图兼容所有版本。我建议只支持 3.x因为 2.x 已经停止维护了。4.6 自动化流水线的搭建导出器写完之后要把它集成到项目的构建流程里。我的做法是用一个Makefile或者npm script把整个流程串起来# 从画布工具拉取最新布局 canvas-cli export --fileui-design.json # 生成三个引擎的 UI 文件 python export.py --inputui-design.json --targetunity --outputAssets/UI/ python export.py --inputui-design.json --targetgodot --outputscenes/ui/ python export.py --inputui-design.json --targetcocos --outputassets/ui/ # 提交到 Git git add Assets/UI/ scenes/ui/ assets/ui/ git commit -m chore: update UI from canvas如果团队用 CI/CD可以把这段脚本挂到流水线上每次画布更新自动触发导出和提交。这样美术改完画布程序拉一下代码就能看到最新的 UI 结构不需要手动同步。5. 常见问题与排查技巧实录5.1 坐标偏移与缩放异常问题表现导出的 UI 在引擎里位置偏了或者尺寸不对。排查思路先检查画布节点的absoluteBoundingBox是不是相对于根节点的。有些画布工具的 API 返回的是相对于父节点的坐标有些是相对于画布的。如果搞混了导出的坐标就会叠加偏移。解决方法在解析层统一转换成相对于根节点的绝对坐标。如果画布工具返回的是相对坐标就递归累加父节点的坐标。另外检查画布的缩放比例如果画布本身有缩放导出的坐标要除以缩放系数。我的经验在导出器里加一个--debug模式把每个节点的原始坐标和转换后坐标都打印出来对比一下就能发现问题。5.2 字体丢失与乱码问题表现导出的 UI 在引擎里显示方块或者乱码。排查思路先确认字体映射表里有没有对应的字体。如果映射表里有检查字体文件是否在项目里路径是否正确。如果路径正确检查字体的字符集是否包含所需字符。中文字体尤其容易出问题因为很多英文字体不包含中文字符。解决方法在导出器里加一个字符集检查步骤遍历所有文本节点提取字符跟字体文件的字符集对比。缺失的字符在日志里警告。另外Godot 和 Cocos 对动态字体的支持方式不同Godot 用FontFile的fallbacks属性Cocos 用Label的cacheMode。导出器要根据引擎特性做适配。提示如果项目有多语言需求建议每个语言单独导出一份 UI而不是在运行时动态切换字体。因为动态切换字体在三个引擎里的实现方式都不一样容易出兼容性问题。5.3 图片资源引用失效问题表现导出的 UI 在引擎里图片显示不出来或者显示成白块。排查思路检查图片路径是否正确。Unity 的图片路径是相对于Assets目录的Godot 是相对于res://的Cocos 是相对于resources的。如果路径不对资源就加载不了。另外检查图片的导入设置Unity 的图片要设成Sprite类型Godot 要设成Texture2DCocos 要设成SpriteFrame。解决方法在导出器里维护一个资源映射表记录画布里的图片名称到引擎资源路径的对应关系。导出的时候查表填路径。如果表里没有就在日志里警告提醒手动添加。5.4 层级顺序错乱问题表现导出的 UI 在引擎里层级不对该在上面的跑到下面去了。排查思路检查节点树的遍历顺序。画布工具的节点顺序通常是从下到上引擎的渲染顺序通常是从上到下。如果导出器没有反转顺序层级就会颠倒。解决方法在生成层里把子节点的顺序反转一下。Unity 的m_Children数组顺序决定了渲染顺序数组前面的先渲染后面的后渲染。Godot 的节点顺序也是先渲染前面的。Cocos 的_children数组顺序同理。5.5 常见问题速查表问题现象可能原因排查方法解决方案坐标偏移坐标系原点不一致打印原始和转换后坐标统一坐标系Y 轴取反尺寸不对画布缩放未处理检查画布缩放系数坐标除以缩放系数字体乱码字体缺失或字符集不全检查字体映射表和字符集补充字体或字符图片白块资源路径错误检查资源映射表修正路径或导入设置层级颠倒子节点顺序未反转检查生成的文件顺序反转子节点数组按钮点不动射线检测目标缺失检查按钮的 target 配置添加 Graphic 或 target文本截断尺寸计算错误检查文本节点的尺寸重新计算或开启自动换行5.6 独家避坑技巧技巧一先导出静态 UI再挂逻辑。不要一上来就试图导出带交互的完整 UI。先把静态布局跑通确认坐标、样式、层级都对了再逐步加按钮、滚动、输入框这些交互组件。这样出问题的时候排查范围小很多。技巧二用 Git 管理导出产物。导出的.prefab、.tscn文件虽然是自动生成的但也要提交到 Git。这样每次导出之后diff 能看出改了哪些节点方便 review。如果发现导出结果不对直接回滚到上一个版本就行。技巧三保留画布源文件。画布文件是唯一的真相来源导出产物只是中间结果。任何时候都要以画布为准不要在引擎里手动改导出的 Prefab因为下次导出会覆盖掉。如果确实需要在引擎里做特殊处理用脚本或者额外的节点挂载不要改导出生成的部分。技巧四定期做全量导出测试。每次画布有大改动之后做一次全量导出三个引擎都跑一遍确认没有报错。不要等到发布前才做那时候问题堆积起来很难排查。技巧五给导出器加版本号。中间格式和导出器都要有版本号画布文件里记录它用的中间格式版本。导出器检查版本号不匹配就报错。这样避免因为格式升级导致的老文件解析失败。6. 跨引擎协作的扩展思路6.1 从 UI 扩展到场景和动画这套画布导出的思路不只适用于 UI还可以扩展到场景布局和简单动画。画布工具里的节点位置、尺寸、层级本质上就是场景描述。如果画布工具支持时间轴或者关键帧还能导出简单的动画数据。我试过用画布工具做关卡布局导出到 Godot 的TileMap和 Unity 的Tilemap。思路是一样的画布里用不同颜色的矩形表示不同的地块导出器根据颜色映射到对应的 Tile 资源。这样策划在画布里拖拖拽拽就能做关卡不需要学引擎的编辑器。动画的导出稍微复杂一些因为画布工具的关键帧格式跟引擎的动画系统差异很大。但简单的位移、缩放、透明度动画是可以映射的。Unity 用AnimationClipGodot 用AnimationPlayerCocos 用Animation组件。导出器把画布的关键帧数据转成引擎的动画格式。6.2 与设计系统的结合如果团队有设计系统Design System画布导出可以跟它深度结合。设计系统里定义了颜色、字体、间距、圆角等设计令牌Design Token画布工具里的样式都引用这些令牌。导出器读取令牌值生成引擎里的样式配置。这样做的好处是改一处全局生效。比如品牌色从蓝色改成红色只需要改设计令牌重新导出三个引擎的 UI 全部更新。不需要在每个引擎里手动改颜色。实现方式是在中间格式里存令牌的引用而不是具体的值。导出器根据令牌引用去查令牌表拿到实际值再填到引擎文件里。令牌表可以用 JSON 维护跟画布文件一起版本管理。6.3 自动化测试与视觉回归UI 导出最容易出的问题是“改了一个地方另一个地方坏了”。这种回归问题靠人工检查很难发现尤其是 UI 界面多的时候。我的做法是加一层视觉回归测试。具体流程是每次导出之后用引擎的截图功能把 UI 渲染出来跟上一版的截图做像素对比。差异超过阈值的标记为可疑人工确认。Unity 可以用ScreenCapture.CaptureScreenshotGodot 用get_viewport().get_texture().get_image()Cocos 用Camera的render方法。这个测试不需要跑在 CI 上本地开发的时候跑一下就行。关键是建立基线第一次导出的截图作为基准后续每次导出都跟基准对比。如果是有意的改动更新基准如果是无意的回滚代码。提示视觉回归测试的阈值不要设得太低因为不同引擎的渲染有细微差异像素级对比会误报。我的经验是差异超过 2% 才报警低于这个值忽略。6.4 团队协作流程的调整引入画布导出流程之后团队的协作方式也要跟着调整。美术不再需要学引擎的 UI 编辑器只需要在画布里工作。程序不再需要手动摆 UI 节点只需要在导出的骨架上挂脚本。策划改文案的时候直接在画布里改重新导出就行。但这也带来了新的挑战。第一画布文件的权限管理。画布文件是唯一的真相来源不能随便让人改。建议用画布工具的团队协作功能设置不同角色的权限。第二导出流程的自动化。不能让美术手动跑导出脚本要集成到 CI 或者用画布工具的 webhook 自动触发。第三沟通成本。美术和程序需要约定好命名规范、层级规范、导出标记这些规范要写成文档新成员入职的时候培训。我个人的体会是这套流程的收益在项目初期不明显甚至因为要写导出器而增加了一些工作量。但到了项目中后期UI 频繁迭代的时候收益就体现出来了。改一个按钮的位置从原来的“美术切图、程序摆节点、测试验证”变成“美术改画布、自动导出、测试验证”省掉了中间最耗时的一环。最后再分享一个小技巧如果团队暂时没有精力写完整的导出器可以先用画布工具的插件市场找现成的方案。Figma 有Figma to Unity、Figma to Godot的插件虽然功能不一定完全满足需求但可以作为起点在此基础上改。自己从零写导出器大概需要两到三周用现成插件改的话一周左右就能跑通基本流程。
返回列表