目录

Unity + Flutter 混合开发全指南:在 Flutter 中嵌入 3D 游戏的完整流程

一、为什么选择 Unity + Flutter 混合开发?

二、环境准备与工具链

1. 必备开发工具

2. 版本兼容性注意

三、Step 1:Unity 端开发与配置

1. 创建 Unity 3D 项目

2. 导入 Unity-Flutter 通信插件

3. 编写 3D 逻辑与通信脚本

4. 配置 Unity 导出设置

(1)Android 平台配置

(2)iOS 平台配置

四、Step 2:Flutter 端项目创建与集成

1. 新建 Flutter 项目

2. 添加 Unity 集成插件

3. 编写 Flutter 界面与通信逻辑

五、Step 3:项目关联与打包运行

1. 导出 Unity 工程到 Flutter 项目

(1)Android 平台

(2)iOS 平台

2. 平台配置调整

(1)Android 配置

(2)iOS 配置

3. 运行与测试

(1)Android 运行

(2)iOS 运行

六、常见问题与解决方案

1. 通信失败(Flutter 调用 Unity 无响应)

2. 打包 APK 闪退

3. iOS 编译错误 “Undefined symbols for architecture arm64”

七、总结


在移动开发中,Flutter 以其跨平台 UI 一致性和高效开发著称,但在复杂 3D 游戏开发方面并非专长;而 Unity 作为专业 3D 引擎,在渲染、物理系统和动画方面优势显著。将两者结合,既能利用 Flutter 快速构建美观的跨平台 UI,又能借助 Unity 实现高质量 3D 游戏场景。本文将带你从零开始,完成 Unity 3D 游戏嵌入 Flutter 应用的全流程,包括环境搭建、双向通信、打包发布等关键步骤。

一、为什么选择 Unity + Flutter 混合开发?

这种组合的核心价值在于优势互补

  • Unity:负责 3D 场景渲染、物理碰撞、骨骼动画等核心游戏逻辑,提供专业级 3D 开发能力;
  • Flutter:负责应用 UI 界面、业务逻辑、网络请求等,实现跨平台一致性体验;
  • 适用场景:3D 游戏(如角色冒险、虚拟漫游)、高保真交互场景(如 AR 看房、3D 教育)。

相比纯 Unity 或纯 Flutter 方案,混合开发能兼顾3D 性能UI 灵活性,同时降低跨平台适配成本。

二、环境准备与工具链

1. 必备开发工具

工具版本要求作用
Unity2020.3 LTS 或 2021.3 LTS开发 3D 游戏核心场景
Flutter3.0+构建跨平台应用 UI
Android Studio4.0+Android 平台编译与调试
Xcode13.0+(Mac)iOS 平台编译与调试
插件flutter_unity_widget实现 Flutter 与 Unity 通信

2. 版本兼容性注意

  • Unity 2019 及以下版本可能不支持最新插件,建议使用 2020+ LTS 版本;
  • Flutter 需 3.0+ 以支持 flutter_unity_widget 4.0+
  • Android 端:Unity 与 Flutter 的 Gradle 版本需一致(推荐 7.0+);
  • iOS 端:需 Xcode 13+ 支持 Unity 导出的工程格式。

三、Step 1:Unity 端开发与配置

1. 创建 Unity 3D 项目

  • 打开 Unity Hub,新建 3D 模板项目(示例命名为 Unity3DGame);
  • 导入基础资源:添加一个简单的 3D 房间模型和可移动的人物模型(可从 Unity Asset Store 下载免费资源)。

2. 导入 Unity-Flutter 通信插件

  • 打开 Unity 项目,进入 Window > Package Manager
  • 点击 + > Add package from git URL,输入插件地址:
    https://github.com/juicycleff/flutter-unity-view-widget.git?path=/packages/unity_bridge
    (若无法访问 Git,可手动下载源码并导入 unity_bridge 目录)。

3. 编写 3D 逻辑与通信脚本

以 “人物移动控制” 为例,创建 C# 脚本 PlayerController.cs,实现 3D 人物控制并与 Flutter 通信:

using UnityEngine;
using FlutterUnityIntegration; // 引入通信库

public class PlayerController : MonoBehaviour
{
    public float moveSpeed = 5f; // 移动速度
    private Rigidbody rb; // 刚体组件(用于物理移动)

    void Start()
    {
        // 获取人物刚体组件(需在编辑器中手动添加)
        rb = GetComponent<Rigidbody>();
        // 禁用重力与旋转锁定(避免人物倾倒)
        rb.useGravity = false;
        rb.freezeRotation = true;
    }

    // 接收 Flutter 发送的移动指令
    public void Move(string direction)
    {
        // 根据指令计算移动方向
        Vector3 movement = Vector3.zero;
        switch (direction)
        {
            case "forward": movement = Vector3.forward; break;
            case "back": movement = Vector3.back; break;
            case "left": movement = Vector3.left; break;
            case "right": movement = Vector3.right; break;
        }
        // 应用移动(通过刚体实现平滑物理移动)
        rb.velocity = movement * moveSpeed;

        // 向 Flutter 发送当前位置(可选)
        UnityMessageManager.Instance.SendMessageToFlutter(
            "player_position", 
            $"X: {transform.position.x:0.0}, Y: {transform.position.y:0.0}, Z: {transform.position.z:0.0}"
        );
    }
}

  • 在 Unity 编辑器中,将脚本挂载到人物模型上;
  • 给人物模型添加 Rigidbody 组件(在 Inspector 面板点击 Add Component > Rigidbody)。

4. 配置 Unity 导出设置

(1)Android 平台配置
  1. 进入 File > Build Settings,切换平台为 Android
  2. 点击 Player Settings,设置关键参数:
    • Company Name:与 Flutter 项目一致(如 com.example);
    • Product Name:自定义名称(如 Unity3DGame);
    • Minimum API Level:Android 19+(与 Flutter 兼容);
    • Scripting Backend:选择 IL2CPP(支持 64 位,性能更好);
    • Target Architectures:勾选 ARM64 和 ARMv7
(2)iOS 平台配置
  1. 进入 File > Build Settings,切换平台为 iOS
  2. 点击 Player Settings,设置:
    • Bundle Identifier:与 Flutter 项目前缀一致(如 com.example.unitygame);
    • Minimum iOS Version:11.0+。

四、Step 2:Flutter 端项目创建与集成

1. 新建 Flutter 项目

flutter create unity_flutter_demo
cd unity_flutter_demo

2. 添加 Unity 集成插件

在 pubspec.yaml 中添加依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_unity_widget: ^4.0.2  # 最新版本可在 pub.dev 查询

执行 flutter pub get 安装插件。

3. 编写 Flutter 界面与通信逻辑

创建 unity_game_page.dart,实现包含 Unity 3D 视图和控制按钮的页面:

import 'package:flutter/material.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';

class UnityGamePage extends StatefulWidget {
  const UnityGamePage({super.key});

  @override
  State<UnityGamePage> createState() => _UnityGamePageState();
}

class _UnityGamePageState extends State<UnityGamePage> {
  late UnityWidgetController _unityController;
  String _playerPosition = "等待人物移动...";

  // Unity 初始化完成回调
  void _onUnityCreated(UnityWidgetController controller) {
    _unityController = controller;
  }

  // 接收 Unity 发送的消息(如人物位置)
  void _onUnityMessage(UnityMessage message) {
    if (message.name == "player_position") {
      setState(() => _playerPosition = "人物位置:${message.data}");
    }
  }

  // 向 Unity 发送移动指令
  void _sendMoveCommand(String direction) {
    _unityController.postMessage(
      "Player",   // Unity 中人物模型的名称(必须与编辑器中一致)
      "Move",     // 调用的 C# 方法名(与 PlayerController 中一致)
      direction   // 传递的参数(移动方向)
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Unity + Flutter 3D 示例")),
      body: Column(
        children: [
          // 显示 Unity 3D 场景(占满屏幕主要区域)
          Expanded(
            child: UnityWidget(
              onUnityCreated: _onUnityCreated,
              onUnityMessage: _onUnityMessage,
              unityScene: "Assets/Scenes/MainScene.unity", // Unity 场景路径
            ),
          ),
          // 显示人物位置信息
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(_playerPosition, style: const TextStyle(fontSize: 16)),
          ),
          // 移动控制按钮
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                icon: const Icon(Icons.arrow_upward, size: 32),
                onPressed: () => _sendMoveCommand("forward"),
              ),
              IconButton(
                icon: const Icon(Icons.arrow_downward, size: 32),
                onPressed: () => _sendMoveCommand("back"),
              ),
              IconButton(
                icon: const Icon(Icons.arrow_left, size: 32),
                onPressed: () => _sendMoveCommand("left"),
              ),
              IconButton(
                icon: const Icon(Icons.arrow_right, size: 32),
                onPressed: () => _sendMoveCommand("right"),
              ),
            ],
          ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }
}

在 main.dart 中设置入口:

import 'package:flutter/material.dart';
import 'unity_game_page.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Unity + Flutter",
      home: const UnityGamePage(),
    );
  }
}

五、Step 3:项目关联与打包运行

1. 导出 Unity 工程到 Flutter 项目

(1)Android 平台
  • 在 Unity 中,File > Build Settings,勾选 “Export Project”,点击 “Export”;
  • 选择导出路径:flutter项目根目录/android/unityLibrary(自动创建该文件夹);
  • 导出完成后,Flutter 会自动识别 Unity 模块。
(2)iOS 平台
  • 在 Unity 中,File > Build Settings,点击 “Build”,导出 iOS 工程到 flutter项目根目录/ios/UnityLibrary
  • 用 Xcode 打开 Flutter 项目的 iOS 工程:flutter项目根目录/ios/Runner.xcworkspace
  • 右键点击 “Runner” 项目,选择 “Add Files to Runner”,导入 Unity 导出的 UnityLibrary.xcodeproj

2. 平台配置调整

(1)Android 配置
  • 打开 android/build.gradle,确保 minSdkVersion 与 Unity 一致:

    buildscript {
      ext {
        minSdkVersion = 19  // 需 ≥ Unity 设置的最低版本
        compileSdkVersion = 33
        targetSdkVersion = 33
      }
    }
    
  • 打开 android/settings.gradle,确认 Unity 模块已添加:

    include ':unityLibrary'
    project(':unityLibrary').projectDir = file('./unityLibrary')
    
(2)iOS 配置
  • 在 Xcode 中,选中 “Runner” 项目,设置 Minimum Deployments 为 11.0+;
  • 选中 “UnityLibrary” 项目,在 Signing & Capabilities 中配置与 Runner 一致的签名;
  • 在 Build Settings > Other Linker Flags 中添加 -ObjC(解决链接错误)。

3. 运行与测试

(1)Android 运行

# 查看设备列表
flutter devices
# 运行到指定设备
flutter run --device-id <设备ID>
(2)iOS 运行
  • 在 Xcode 中选择连接的 iOS 设备,点击运行按钮(▶️);
  • 首次编译可能需要 5-10 分钟(Unity 资源打包)。

成功运行后,你将看到:

  • Flutter 界面顶部显示 Unity 3D 场景;
  • 底部的方向按钮可控制人物移动;
  • 人物位置信息会实时同步到 Flutter 界面。

六、常见问题与解决方案

1. 通信失败(Flutter 调用 Unity 无响应)

  • 检查名称匹配postMessage 的第一个参数(物体名称)必须与 Unity 场景中人物模型的名称完全一致(区分大小写);
  • 方法名错误:C# 脚本中的方法名(如 Move)必须与 Flutter 调用的名称一致;
  • 插件版本不匹配:确保 Unity 插件 unity_bridge 与 Flutter 插件 flutter_unity_widget 版本对应。

2. 打包 APK 闪退

  • 权限缺失:在 android/app/src/main/AndroidManifest.xml 中添加权限:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    
  • Gradle 冲突:统一 Unity 和 Flutter 的 Gradle 版本(在 unityLibrary/build.gradle 中修改)。

3. iOS 编译错误 “Undefined symbols for architecture arm64”

  • 在 Xcode 中,为 UnityLibrary 项目的 Other Linker Flags 添加 -ObjC
  • 确认 Unity 导出时勾选了 ARM64 架构(在 Player Settings 中设置)。

七、总结

Unity 与 Flutter 的混合开发,完美结合了专业 3D 引擎与跨平台 UI 框架的优势。通过本文的步骤,你可以实现:

  1. Unity 3D 场景在 Flutter 中的无缝嵌入;
  2. 双向通信(Flutter 控制 3D 人物,Unity 反馈状态);
  3. 跨 Android/iOS 平台的一致体验。

这种方案适合开发中大型 3D 游戏或高保真交互场景,虽然初期配置稍显复杂,但一旦搭建完成,后续开发可专注于业务逻辑,大幅提升开发效率。

如果需要进一步优化,可探索:

  • 更复杂的通信协议(如 JSON 数据传输);
  • Unity 场景与 Flutter UI 的深度融合(如半透明叠加);
  • 资源热更新方案(结合 Firebase 或自定义服务器)。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐