当 Flutter 撞上 3D 性能之墙 —— Fluorite(萤石)

0 阅读12分钟

丰田如何利用 Flutter + C++ 打造出主机级的游戏引擎

image.png

原始演讲:FOSDEM 2026

演讲者:Jamie Kerber(Very Good Ventures 资深工程师 / Fluorite 首席工程师)

代表人员:Joel Winarski(丰田北美互联公司 首席工程师 / Fluorite 创始人)

前言:当 Flutter 撞上 3D 性能之墙

丰田已经在量产车中搭载了 Flutter。2026 款 RAV4 的车载信息娱乐系统就运行在 Flutter 的嵌入式堆栈上。但传统的 Flutter 仅支持 2D 渲染,对于汽车应用场景来说,这还远远不够。

想象一下这个场景:你需要一个 3D 交互式车主手册,驾驶员可以旋转汽车模型,点击轮胎查看胎压,或者拖动滑块来调节悬架高度。实时硬件状态可视化、环境贴图投影——这一切都需要一个游戏引擎。

问题在于:现有的游戏引擎中,没有一个能与 Flutter 嵌入式系统完美集成。丰田互联(Toyota Connected)给出的答案?从零开始自研一个。

当我第一次看到这个演讲题目时,我以为这只是另一个“公司开源内部工具”的故事。但在看完之后,我意识到他们正在解决的问题远比我预期的要复杂。而且,这不仅仅是丰田一家公司面临的难题。

1. 为什么现有的游戏引擎行不通?

丰田团队并没有偷懒。他们测试了市场上每一个主流选项,结论非常明确:全部失败。

  • 首先是商业闭源引擎: Unity 和 Unreal 要求在你的 Linux 发行版中携带闭源的二进制大对象(Proprietary Blobs)——这直接断绝了与 Yocto 的兼容性。在嵌入式 Linux 世界中,Yocto 是标准构建系统,你绕不开它。更糟的是,每个原生视图(Native View)都会生成一个完整的引擎实例,导致帧率大幅下降。再加上每年可能高达数百万美元的授权费,这对汽车制造商来说在财务上根本行不通。
  • 那么开源方案 Godot 呢? 虽然没有授权费问题,但在树莓派 5(Raspberry Pi 5)上,仅启动就需要超过 20 秒。驾驶员上车、发动汽车、屏幕亮起,然后要等 20 秒才能看到 3D 界面?那是耐心测试,不是用户体验。
  • 最后是 Flutter GPU (Impeller): 理论上它是完美契合的:原生 Flutter 集成、Dart 语言、热重载。实际上呢?它在 iOS 上很稳定,在 Android 上不稳定,而在 Linux / macOS / Windows 上简直无法使用。对于运行嵌入式 Linux 的车载系统来说,它等同于不存在。

在测试完所有方案后,丰田得出了一个冷酷的结论:目前没有任何方案能同时满足“Flutter 集成 + 嵌入式支持 + 高性能 3D + 开源授权”这四大需求。

image.png

于是,他们决定自研。

这反映出 Flutter 生态系统中一个更深层次的断层:Flutter 已经在 2D UI 领域拔得头筹,但当你需要底层图形能力的那一刻,你会发现脚下空无一物。无论是 AR 滤镜、点云可视化,甚至是稍显复杂的着色器(Shader)特效,都在逼着 Flutter 开发者不得不通过平台通道(Platform Channels)把工作丢回原生端去处理。Fluorite 正是试图为整个生态系统填补这一空白,而不只是为了丰田。

2. 什么是 Fluorite?

可以把它想象成盖房子。Flutter 是你的室内设计师——负责按钮、列表、动画和页面转场,它处理所有的 2D 事务。但现在你想在客厅装一面互动的 3D 屏幕墙,你不会为了装这面墙就把整座房子推倒重建,而是会找一个能嵌入现有结构的模块。

Fluorite 就是那个模块。

它是来自丰田互联(Toyota Connected)的开源 3D 游戏引擎,以 Flutter Package 的形式提供,直接集成到你的应用中。没有额外的运行环境,不需要复杂的原生视图黑科技(Platform View Hacks)。只需在 pubspec.yaml 中添加一行代码,你就拥有了一个 3D 引擎。

简而言之,FluoriteView 就是一个 Widget。

这个设计方向是正确的。Flutter 开发者对 Widget 的认知是“轻量、可组合、随处安放”。Fluorite 保留了这一心智模型,而不是丢给你一个需要特殊处理的“异物”。它遵循 Flutter 的布局系统,可以出现在任何地方:Column 内部、Stack 之上,或是 TabView 的某个标签页里。你甚至可以在同一个屏幕上放置多个 FluoriteView 实例,每个实例展示不同的 3D 视角。

而且,3D 游戏对象可以通过 Provider / Riverpod / Bloc 与 Flutter UI 组件进行交互。你已经掌握的每一种状态管理方案都能直接无缝协作。

image.png

3. 技术架构

Fluorite 并不是凭空捏造出来的。你可以把它想象成一个“三明治”结构:顶层是供你调用的 Dart API,中层是负责性能处理的 C++ 核心,而底层则构建在两个经受过验证的开源引擎之上。

  • 顶层:Dart API 开发者只需要接触这一层 —— 创建实体(Entities)、挂载组件(Components)、编写行为脚本,这一切全都使用 Dart 语言完成。

  • 中层:C++ ECS 核心 为什么不全部用 Dart 编写?因为嵌入式设备的内存和 CPU 资源非常有限。C++ 让团队能够精确控制内存分配和处理管线,从而从树莓派(Raspberry Pi)这类低端硬件中榨取最大性能。

  • 底层:两大支柱

    • Google Filament:负责 3D 渲染。它与驱动 Android 系统 UI 的是同一个引擎,在 Vulkan 1.1+ 上实现全硬件加速,支持 PBR(基于物理的渲染) 、HDR 光影,以及基于 GLSL 超集的自定义着色器管线。
    • SDL3:负责跨平台 I/O,统一了不同嵌入式设备上的输入/输出和窗口管理。

image.png

用一句话总结这个架构:Dart 负责逻辑,C++ 负责性能,Filament 负责渲染,SDL3 负责平台抽象。

4. ECS —— 其实你早就懂了

如果你曾经在 Unity 中给物体挂载过 Transform 组件,那么恭喜你 —— 你已经使用过“实体组件系统”(ECS)了。

ECS 是游戏引擎中最流行的架构模式。你可以把它想象成乐高积木:一个“实体(Entity)”就是一块空白底板,它本身什么都不是;“组件(Components)”则是你按在上面的积木块 —— 位置信息、碰撞体、3D 模型、行为脚本;而“系统(System)”每一帧都会扫描所有实体,寻找带有特定组件组合的对象并执行逻辑。

Fluorite 的 API 完全遵循这一模式 —— 唯一的区别仅仅是编程语言从 C# 切换到了 Dart:

// A bouncing ball — looks almost identical to Unity's GameObject
final bouncingBall = Entity(
  name: 'BouncingBall',
  components: [
    Transform(
      position: Vector3(0, 5, 0),   // Starting position: 5m in the air
      scale: Vector3(1, 1, 1),
      rotation: Quaternion.identity(),
    ),
    SphereCollider(radius: 0.5),     // Collision boundary
    ModelRenderable(asset: 'assets/ball.glb'),  // 3D model
    BehaviorScript(
      onCreate: (entity) { /* initialization logic */ },
      onUpdateFrame: (entity, deltaTime) {
        // Per-frame update: gravity, bounce, displacement
      },
    ),
  ],
);

变换(Transform)、碰撞体(Collider)、可渲染体(Renderable)、行为脚本(Behavior Script)——如果你是从 Unity、Unreal 或 Godot 阵营过来的,闭着眼睛都能认出这些概念。

image.png

Fluorite 还提供了一个“层级场景图 (Hierarchical Scene Graph)”,用于构建复杂的嵌套对象结构。车身是父级实体(Parent Entity),四个车轮是子级实体(Child Entities),每个车轮上又挂载了胎压传感器 —— 这与任何其他主流游戏引擎完全一致。近乎零的迁移成本:如果你能在 Unity 中构建场景,你就能在 Fluorite 中构建。

话虽如此,“低迁移成本”主要适用于你有游戏开发经验的情况。如果你是一名从未接触过游戏引擎的纯 Flutter 开发者,ECS(实体组件系统)的心智模型与你习惯的 Widget 树大不相同。Widget 是声明式的 UI 描述,而 ECS 是基于每一帧的系统循环。这其中存在学习曲线。Fluorite 将 ECS 封装在 Dart API 之下,因此你不需要理解系统调度就能开始构建。但如果你想做出超越 Demo 级别的场景,理解 ECS 的数据流就变得至关重要了。

5. 艺术家与开发者如何协作

传统游戏开发有一个长期的痛点:艺术家创建 3D 模型,交给开发者,然后开发者花费数小时标记交互区域、设置碰撞边界并绑定事件。当艺术家修改模型时,开发者就得重做一遍。

Fluorite 的答案是:模型定义触摸触发区 (Model-Defined Touch Trigger Zones)。

核心思路:让 3D 艺术家直接在 Blender 中使用命名规范来标记交互区域。对于一个汽车模型,艺术家将每个轮胎标记为 trigger_tire_FLtrigger_tire_FR 等。在开发侧,你只需要写:“当 trigger_tire_FL 被点击时,打开胎压面板。”

实际操作中的表现:

  • 点击 3D 汽车模型上的轮胎 → 调整胎压数值
  • 拖动 Flutter 的 Slider 滑块 → 实时更新 3D 胎压指示器
  • 游戏状态(Game State)与 Flutter UI 始终保持完美同步

image.png

最大的赢点在于:艺术家和开发者可以完全并行工作。艺术家在 Blender 中调整模型,而开发者在 Dart 中编写交互逻辑,双方通过 GLTF/GLB 格式交换资源,无需互相等待。

6. 以 Dart 为中心的开发体验

使 Fluorite 脱颖而出的原因可以用一句话总结:你在 Dart 中编写游戏逻辑,在 Flutter 中编写 UI,两者都在同一个项目中完成。

在实践中这究竟意味着什么?

UI 和游戏逻辑都使用 Dart 编写。无需在 C# 和 Dart 之间进行上下文切换。状态管理、模型类以及工具函数全都是共享的;不需要维护两套代码库。热重载(Hot Reload)、Widget Inspector 以及 DevTools 全都可用。微调一下摄像机的轨道距离,点击保存,3D 场景在不到一秒钟内就会更新。相比之下,其他游戏引擎的编译时间往往长达数十秒。而且,整个 pub.dev 生态系统都可以直接调用。

以下是它与其他备选方案的对比:

image.png

Fluorite 是目前唯一能勾选该表所有选项的解决方案。

7. 现实考量:风险在哪里?

技术本身很扎实,但在投入之前,有几件事值得深思。

  • Impeller 的阴影: Flutter 官方的 Impeller 渲染引擎仍在活跃开发中。如果两年后 Impeller 增加了 Linux 和桌面端的 3D 能力,Fluorite 的定位会变得有些尴尬。你是选择官方方案,还是第三方引擎?虽然 Fluorite 提供的 ECS 架构和嵌入式优化是 Impeller 不具备的,但两者功能的重叠值得持续关注。

8. 路线图与资源格式

已完成

  • C++ ECS 核心引擎
  • Filament 3D 渲染集成
  • Dart API 层
  • 层级场景图 (Hierarchical Scene Graph)
  • 模型定义的触摸触发区
  • 热重载 (Hot Reload) 支持
  • PBR 材质 + HDR 光照
  • 自定义着色器管线

进行中 / 计划中

  • Jolt 物理引擎集成 —— 刚体/软体物理模拟,以组件(Components)形式挂载
  • CLI / GUI 工具 —— 支持设计师与开发者的工作流
  • 全跨平台支持 —— 嵌入式 Linux (包含 Yocto)、iOS、Android、macOS、Windows、游戏主机
  • SDL3 Dart API —— 将 SDL3 的能力作为 Package 开放给 Flutter 社区

资源格式

  • 当前支持格式:3D 模型使用 GLTF / GLB(完全兼容 Blender);纹理支持 KTX、HDR 等常见格式;着色器使用 GLSL 超集
  • 如果你已有来自 Unity / Unreal / Godot 的 GLTF 资源,几分钟内即可将其迁移至 Fluorite。

9. 这对 Flutter 开发者意味着什么

Fluorite 是一款 3D 游戏引擎,但更宏观的意义在于:Flutter 正在从“UI 工具包”演变为“应用平台”。

Flutter 始于纯移动端框架,随后扩展至 Web、桌面和嵌入式。每一次人们都说“Flutter 不适合这个”,但每一次都有团队用量产产品证明他们错了。Fluorite 是最新的跨越。丰田证明了 Flutter 可以运行主机级的 3D 渲染。

这并不意味着每个 Flutter 开发者明天都要去学 ECS。但如果你下一个项目需要 3D 产品展示、AR 交互、数据可视化或简单的游戏,你不再需要离开 Flutter 生态。

你现在可以做的:

  • 关注 fluorite.game 以获取仓库公开的动态。一旦公开,运行一下示例项目。即使你最终不用它,花一个小时感受一下“Dart + 3D”也是值得的。
  • 跟踪 Impeller 的桌面端进展。如果你看重 3D 但不需要嵌入式支持,Impeller 可能更轻量。同时关注两者,在时机成熟时做出选择。
  • 审视当前项目。哪些地方受到了 2D 的限制?产品模型展示、空间数据可视化、游戏化引导。这些过去需要 WebView 或平台通道绕路实现的功能,现在有了原生选项。

Fluorite 目前还没有公开仓库,但我正在盯着 fluorite.game。开放的那一刻,我会立即尝试。有些东西不能仅凭一场演讲来判断,你必须亲手写代码。

Flutter 的 3D 故事才刚刚开始。Fluorite 可能不是最终答案,但它是目前唯一在认真尝试的方案。