news 2026/8/18 15:52:24

用JSON定义游戏界面:FlatUI序列化功能完整上手教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用JSON定义游戏界面:FlatUI序列化功能完整上手教程

用JSON定义游戏界面:FlatUI序列化功能完整上手教程

【免费下载链接】flatuiEfficient Immediate Mode UI for Games项目地址: https://gitcode.com/gh_mirrors/flatu/flatui

FlatUI 是 Google 开源的高效即时模式(Immediate Mode)游戏 UI 库,主打轻量、快速、零状态管理的界面渲染方案。而它的序列化功能(Serialization)更是让开发者可以用 JSON 直接定义游戏界面,把界面布局与 C++ 代码彻底分离,堪称游戏开发者的"界面配置神器"。这篇教程将带你从零上手 FlatUI 序列化,学会用 JSON 快速搭建游戏菜单、配置控件、绑定事件,并扩展自定义控件,全程无需反复编译即可调整界面。

什么是 FlatUI 序列化功能

传统即时模式 UI 中,界面代码和逻辑代码混在一起,改一个按钮位置都要重新编译。FlatUI 序列化功能改变了这一切:它借助FlatBuffers序列化框架,允许你用一份 JSON 文件描述整个游戏界面(控件、布局、尺寸、事件),运行时再解析加载、渲染显示。

它的核心价值在于:

  • 界面与代码解耦:改 UI 文案、颜色、布局只改 JSON,不动 C++ 代码;
  • 天然支持多人协作:策划、美术可以直接编辑 JSON,程序员专注逻辑;
  • 低开销高性能:FlatBuffers 序列化后的二进制数据无需解析即可直接读取,契合游戏对性能的苛刻要求;
  • 支持动态数据与自定义控件:可注册运行时可变的变量,也可扩展专属控件。

FlatUI 序列化核心原理:JSON 到界面的一次旅行

整个流程可以概括为三步:写 JSON → 用 Schema 解析成二进制 → 运行时反序列化渲染

负责这一切的骨架是 flatui.fbs(FlatBuffers Schema 文件),它定义了界面的"语法规则"。其中FlatUIElement是核心表结构,包含了idtypelayouttextsizemarginoffsethorizontalvertical等字段;而Type枚举则列出了 FlatUI 内置支持的控件类型:

控件类型用途常用字段
Label文本标签text、ysize
TextButton文本按钮text、size、margin
Image图片显示texture、ysize
ImageButton图片按钮texture、size
Edit文本输入框ysize、size_2f
Slider滑动条texture、size_2f、bar_size
CheckBox复选框texture、text
ScrollBar滚动条texture、size、bar_size
Group容器分组layout、horizontal、vertical、offset
SetVirtualResolution设置虚拟分辨率virtual_resolution

关于 Schema 的完整字段定义,可以参考 flatui.fbs 中的注释说明。

快速上手:用 JSON 定义第一个游戏界面

我们直接看 FlatUI 自带的序列化示例 first_menu.json,它定义了一个居中的垂直布局菜单,包含标题、按钮和输入框:

{ elements: [ { type: "flatui_data.Type.SetVirtualResolution", id: "virtual resolution", virtual_resolution: 1000 }, { type: "flatui_data.Type.Group", id: "first menu group", layout: VerticalLeft, horizontal: Center, vertical: Center, elements: [ { type: "flatui_data.Type.Label", id: "first menu label", text: "Welcome to the first menu! :D", ysize: 40 }, { type: "flatui_data.Type.Edit", id: "first menu edit text", ysize: 40, size_2f: { x: 0, y: 0 } } ] } ] }

这段 JSON 传达了几个关键信息:

  • type指明控件类型,如LabelGroupEdit
  • id是控件的唯一标识,后续绑定事件、注册动态数据全靠它;
  • layout / horizontal / vertical控制布局方向与对齐方式,Center表示居中;
  • elements支持无限嵌套,实现树形界面结构,与 C++ 中的StartGroup / EndGroup逻辑一一对应。

在 C++ 中加载并渲染 JSON 界面

JSON 写好了,接下来用 C++ 把它加载进游戏。完整的可运行示例在 flatuiserializationsample.cpp,核心流程如下:

  1. 加载文件:读取 JSON、自定义控件 Schema 和主 Schema;
  2. 解析生成二进制:用flatbuffers::Parser结合 Schema 把 JSON 编译成 FlatBuffer 二进制数据;
  3. 创建界面:调用CreateFlatUIFromData()传入二进制数据;
  4. 渲染循环:把创建函数传入flatui::Run()每帧执行。
flatbuffers::Parser parser; parser.Parse(schema.c_str(), include_directories); // 解析 Schema parser.Parse(first_menu_json.c_str()); // 解析 JSON auto* data = parser.builder_.GetBufferPointer(); // 拿到二进制数据 Run(assetman, fontman, input, [&]() { flatui::CreateFlatUIFromData(data, &assetman, event_handler); });

CreateFlatUIFromData是序列化 API 的核心入口,其完整签名定义在 flatui_serialization.h,接受三个参数:FlatBuffer 数据、用于纹理渲染的AssetManager(可选)、以及事件处理器FlatUIHandler(可选)。

事件绑定与动态数据:让界面"活"起来

静态界面没有意义,FlatUI 序列化通过事件绑定动态数据让界面与游戏逻辑联动。

事件处理

事件处理器是一个std::function,接收事件、控件 ID 和动态数据三个参数。示例代码中通过 lambda 包装后传入CreateFlatUIFromData

auto event_handler = & { EventHandler(e, id, dynamic_data, menu_id); };

EventHandler内部按控件id分发逻辑,例如监听"change menu button"的kEventWentUp(松开)事件切换菜单,实现两个菜单之间的来回切换。

动态数据注册

输入框里的文字是运行时可变的,需要用RegisterStringData把它和 JSON 中的控件 ID 绑定:

std::string edit_text_box("Edit me!"); flatui::RegisterStringData("first menu edit text", &edit_text_box);

FlatUI 提供了一套完整的注册函数:RegisterIntDataRegisterFloatDataRegisterBoolDataRegisterVec2DataRegisterVec4Data等,对应DynamicData联合体中的各种数据类型,全部声明在 flatui_serialization.h。注意:注册的指针必须比界面的生命周期更长,否则会引发悬垂指针。

自定义控件:扩展 FlatUI 的专属武器

内置控件不够用时,FlatUI 序列化还支持自定义控件。步骤很简单:

  1. 定义枚举:在自定义 Schema(如 custom_widgets.fbs)中声明控件类型;
  2. 实现渲染函数:编写一个符合CustomWidget签名的函数,用element中的数据调用 FlatUI 绘制 API;
  3. 注册控件:调用RegisterCustomWidget(type, widget)把类型与函数绑定。
void ChangeMenuButton(const flatui_data::FlatUIElement* element, fplbase::AssetManager* assetman, flatui::FlatUIHandler event_handler, flatui::DynamicData* dynamic_data) { flatui::StartGroup(flatui::kLayoutVerticalLeft); flatui::ColorBackground(fplbase::LoadVec4(...)); flatui::Event e = flatui::TextButton(element->text()->c_str(), element->size()); flatui::EndGroup(); event_handler(e, element->id()->str(), dynamic_data); } flatui::RegisterCustomWidget(custom_widgets::Type_ChangeMenuButton, ChangeMenuButton);

自定义控件还能通过attributes字段接收 JSON 中传入的任意参数(颜色、尺寸、对齐方式等),灵活性极高,示例中的"Change Menu"按钮就是典型应用。

调试技巧与常见问题

JSON 写错了怎么办?FlatUI 内置了错误输出机制,默认最多打印 10 条错误,可通过SetErrorOutputCount()调整:

flatui::SetErrorOutputCount(flatui::kNoErrorOutputLimit); // 输出所有错误

常见坑位提醒:

  • JSON 格式不合法:示例代码在Parse失败时会直接报错退出,务必检查括号与逗号;
  • texture 找不到:渲染图片控件时,确保AssetManager中已加载对应纹理资源;
  • id 冲突或遗漏:事件绑定和动态数据都依赖id,命名要全局唯一;
  • Schema 版本不一致:JSON 字段必须与flatui.fbs版本匹配,否则解析报错。

总结:什么时候该用 FlatUI 序列化

如果你正在开发游戏,且满足以下任一场景,强烈建议尝试 FlatUI 序列化功能:

  • 需要频繁调整界面布局,希望免编译热改 UI;
  • 团队中有策划或美术参与界面配置
  • 需要动态生成菜单、弹窗等结构化界面;
  • 追求极低开销的序列化方案(FlatBuffers 天然零拷贝)。

上手方式也很简单:将仓库https://gitcode.com/gh_mirrors/flatu/flatui克隆到本地,直接运行sample/serialization目录下的示例工程,对照 first_menu.json、second_menu.json 和 flatuiserializationsample.cpp 边改边看,很快就能掌握用 JSON 定义游戏界面的全部技巧!

【免费下载链接】flatuiEfficient Immediate Mode UI for Games项目地址: https://gitcode.com/gh_mirrors/flatu/flatui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/18 15:51:36

开发效率提升300%:这套SpringBoot3+Vue3脚手架让你的项目快速启动

项目介绍 基于SpringBoot3、SpringSecurity、MybatisPlus、Vue3、TypeScript、Vite、ElementPlus、MySQL等技术栈实现的单体前后端分离后台管理系统;后端基于Java语言采用SpringBoot3、SpringSecurity、MybatisPlus、MySQL等主流技术栈,前端基于Vue3、T…

作者头像 李华
网站建设 2026/8/18 15:46:14

BilibiliDown使用指南:收藏夹300条内容一键落地的离线视频备份方案

BilibiliDown使用指南:收藏夹300条内容一键落地的离线视频备份方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/…

作者头像 李华
网站建设 2026/8/18 15:45:32

Python进阶 - sys模块 退出程序与异常信息获取

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Python进阶这个话题展开,希望能为你带来一些…

作者头像 李华
网站建设 2026/8/18 15:44:59

用 relly 学 Rust 系统编程:零拷贝与安全内存操作实战

用 relly 学 Rust 系统编程:零拷贝与安全内存操作实战 【免费下载链接】relly RDBMS のしくみを学ぶための小さな RDBMS 実装 项目地址: https://gitcode.com/gh_mirrors/re/relly relly 是一个用 Rust 编写、专为学习而生的迷你 RDBMS(关系型数据…

作者头像 李华