Open Source

Flutter package

unity_kit

Embed Unity 3D in Flutter with a typed, testable bridge — JSON or binary protocol, an enforced lifecycle, AR Foundation, and CDN asset streaming. Runs on Android and iOS (web/WebGL experimental).

v2.0.222.6k / month21 likesMITUnity 2022.3 LTS → Unity 6

Unity export guide

Install the UnityKit scripts, configure the build, and export library artifacts for Android, iOS and WebGL from the Flutter menu.

source: doc/unity-export.md

Before you start

Prerequisites

The Unity project and the Flutter project are completely separate — they can live in different folders, different repos, or even different machines. Build.cs exports Unity as a standalone artifact into a local Builds/ folder; you then optionally deploy that artifact into a Flutter project.

RequirementVersion
Unity Editor2022.3 LTS or newer
Flutter3.0+
unity_kitAdded as a dependency in pubspec.yaml
Android SDKAPI 24+ (for Android export)
Xcode14+ (for iOS export)

Two export modes

Standalone (default)

CI builds, different repos, team workflows

Export to the Builds/ folder and upload it as an artifact

Deploy (optional)

Local development, same machine

Set the Flutter project path in Settings; artifacts are auto-copied on export

Step 1

Install the UnityKit scripts

Copy the entire UnityKit/ folder from the unity_kit package into your Unity project. This ships the message-bridge runtime plus the Editor export automation that adds the Flutter menu.

unity_kit/unity/Assets/Scripts/UnityKit/
YourUnityProject/Assets/Scripts/UnityKit/

Copy the whole folder.

What the folder contains

Assets/Scripts/UnityKit/text
Assets/Scripts/UnityKit/
+-- Editor/
|   +-- Build.cs                      # Export automation (Flutter menu)
|   +-- XCodePostBuild.cs             # iOS Xcode post-processing
|   +-- SweetShellHelper.cs           # Shell helper for build scripts
+-- FlutterBridge.cs                  # Singleton message receiver
+-- FlutterMessage.cs                 # Message DTO: {target, method, data}
+-- FlutterMonoBehaviour.cs           # Base class for Flutter-aware scripts
+-- MessageBatcher.cs                 # Per-frame message batching
+-- MessageRouter.cs                  # Target-based message routing
+-- NativeAPI.cs                      # Platform-specific native calls
+-- SceneTracker.cs                   # Auto scene load/unload notifications
+-- FlutterAddressablesManager.cs     # Addressables integration (optional)
+-- link.xml                          # IL2CPP type preservation

Copy everything — the listing is a subset

The tree above is the documented core, but the real plugin folder ships more files (asmdefs, a Tests/ folder, UnityKitMethodAttribute.cs, UnityKitLogger.cs, FlutterAssetBundleManager.cs, Editor/UnityKitProjectValidator.cs and others). Copy the entire UnityKit/ folder, not just the files named here.

iOS — one extra file, placed before export

The iOS message bridge is an Objective-C++ file that lives outside Assets/Scripts/UnityKit/, so the copy above does not bring it along. Copy unity_kit/unity/Assets/Plugins/iOS/UnityKitNativeBridge.mm into YourUnityProject/Assets/Plugins/iOS/ before exporting for iOS — Unity then includes it automatically in the UnityFramework compile sources.

Open the project in the Unity Editor and wait for scripts to compile. A Flutter menu should appear in the menu bar. If it does not, confirm Assets/Scripts/UnityKit/Editor/Build.cs exists and compiles without errors (Editor scripts must live inside an Editor/ folder).

Reference

The Flutter menu

Once Build.cs compiles, every export and the Settings window are reachable from the Flutter menu. Every item and its keyboard shortcut:

Menu itemShortcutWhat it does
Flutter ▸ Export Android (Debug)Ctrl+Alt+NBuild a debug Android library into Builds/android/unityLibrary/
Flutter ▸ Export Android (Release)Ctrl+Alt+MBuild a release Android library into Builds/android/unityLibrary/
Flutter ▸ Export iOS (Debug)Ctrl+Alt+IBuild a debug iOS UnityLibrary into Builds/ios/UnityLibrary/
Flutter ▸ Export iOS (Release)Build a release iOS UnityLibrary into Builds/ios/UnityLibrary/
Flutter ▸ Export WebGLCtrl+Alt+WBuild a WebGL UnityLibrary into Builds/web/UnityLibrary/ (not production-ready)
Flutter ▸ SettingsCtrl+Alt+SOpen the Settings window: artifact status, Flutter project path, Quick Export, Deploy to Flutter Project, Clean All Builds

Step 5

Export per platform

Exports always go to the Builds/ folder inside your Unity project. If a Flutter project path is configured (see Deploy below), artifacts are also auto-copied there. Switch to the target platform first, then run the matching export.

PlatformSwitch platformExportOutput folder
AndroidFile ▸ Build Settings ▸ Android ▸ Switch PlatformFlutter ▸ Export Android (Debug / Release)<unity-project>/Builds/android/unityLibrary/
iOSFile ▸ Build Settings ▸ iOS ▸ Switch Platform (wait for reimport)Flutter ▸ Export iOS (Debug / Release)<unity-project>/Builds/ios/UnityLibrary/
WebGLFile ▸ Build Settings ▸ WebGL ▸ Switch PlatformFlutter ▸ Export WebGL<unity-project>/Builds/web/UnityLibrary/

Watch the folder casing

Android exports to android/unityLibrary/ (lowercase u), while iOS and WebGL export to ios/UnityLibrary/ and web/UnityLibrary/ (uppercase U). The deploy step copies each into the same-cased folder inside the Flutter project.

Production platforms are Android and iOS only

WebGL export is available but is not production-ready. There is no desktop target, and iOS builds require the Device SDK — the iOS Simulator is not supported.

Automation

What the export does under the hood

A raw Unity export is a standalone app, not something Flutter can embed. Build.cs post-processes each artifact into a library module. On Android, steps 1–9 run on every export; steps 10–12 patch the Flutter project and run only during a deploy.

Android post-processing (every export)

#WhatWhy
1com.android.application → com.android.libraryUnity exports as an app; Flutter needs a library module
2Remove applicationIdLibraries do not have their own app ID
3Add namespace 'com.unity3d.player'Required by Android Gradle Plugin 8+
4Comment out ndkPathConflicts with Flutter's NDK configuration
5Fix ../shared/ → ./shared/Unity 6 shared folder path correction
6Replace fileTree → unity-classes jarCorrect dependency for library mode
7Strip <activity> from the manifestFlutter hosts the activity, not Unity
8Add ProGuard keep rulesPreserve com.unity_kit.** and com.unity3d.player.** from stripping
9Add game_view_content_description stringAccessibility content description

Android — deploy-only Gradle wiring (steps 10–12)

#WhatWhy
10Add include ':unityLibrary' to settings.gradleRegister the Unity module in the Flutter project
11Add a flatDir repositoryResolve unity-classes.jar
12Add implementation project(':unityLibrary') to app/build.gradleWire the dependency in the Flutter app

Gradle DSL — Groovy and Kotlin

Build.cs detects a Kotlin DSL project (build.gradle.kts, Flutter 3.29+) and emits the matching syntax instead of Groovy:

Groovy DSLKotlin DSL
include ':unityLibrary'include(":unityLibrary")
dirs "..."dirs(file("..."))
implementation project(':unityLibrary')implementation(project(":unityLibrary"))

ProGuard keep rules

Step 8 writes these rules so R8/ProGuard cannot strip the bridge classes. If you still see a ClassNotFoundException for com.unity_kit.*, verify they are present in unityLibrary/proguard-unity.txt:

proguard-unity.txttext
-keep class com.unity_kit.** { *; }
-keep class com.unity3d.player.** { *; }

iOS post-processing (XCodePostBuild)

#WhatWhy
1Inject UnityReady NSNotification in startUnity:The unity_kit iOS plugin observes this to know Unity is ready
2Set SKIP_INSTALL = YES on the UnityFramework targetRequired for framework builds
3Set ENABLE_BITCODE = NO on the projectBitcode is deprecated
4Add a Data folder reference to UnityFrameworkRequired for Unity data files to be included

Step 6

Deploy to the Flutter project

Deploying copies whichever artifacts exist in Builds/ into the matching folders in the Flutter project and patches the Android Gradle files. There are three ways to do it.

Builds/android/unityLibrary/
<flutter-project>/android/unityLibrary/
Builds/ios/UnityLibrary/
<flutter-project>/ios/UnityLibrary/
Builds/web/UnityLibrary/
<flutter-project>/web/UnityLibrary/

Option A — Manual deploy from Settings

  1. 1

    Open Flutter ▸ Settings (Ctrl+Alt+S).

  2. 2

    Set the Flutter project path (Browse or paste).

  3. 3

    Click Save Flutter Project Path.

  4. 4

    Click Deploy to Flutter Project.

Option B — Auto-deploy on export

With a Flutter project path configured (in Settings or via the UNITY_KIT_FLUTTER_PROJECT env var), every export automatically copies the artifact to the Flutter project after building — no manual deploy step. The env var wins over the Settings value:

PrioritySourceExample
1 (highest)UNITY_KIT_FLUTTER_PROJECT env varexport UNITY_KIT_FLUTTER_PROJECT=/path/to/app
2EditorPrefs (set via the Settings GUI)Browse button in the Settings window

Option C — CI pipeline

Skip the env var to keep a standalone artifact in Builds/, or set it to auto-copy into the Flutter checkout. See the Headless / CI section below for the exact commands.

The Settings window (Flutter ▸ Settings)

SectionDescription
Build ArtifactsShows the path and build status (BUILT / --) for each platform
Flutter ProjectOptional path to the Flutter project; checks for pubspec.yaml
Quick ExportButtons for every export variant
Deploy to Flutter ProjectCopy the existing artifacts to the configured Flutter project
Clean All BuildsDelete everything in Builds/

Flutter project not detected?

The path must point to the root of a Flutter project (where pubspec.yaml lives). When using the env var, set it before opening Unity. The Settings window validates the path and shows "pubspec.yaml found" or "no pubspec.yaml".

Step 6 · Option C

Headless / CI export

For CI/CD, drive the same exports in batch mode via -executeMethod. The entry points run identical post-processing to the menu items. iOS commands must include -buildTarget iOS.

CI export commandsbash
# Set the Flutter project path (optional -- skip for standalone artifact)
export UNITY_KIT_FLUTTER_PROJECT="/path/to/my_flutter_app"

# Android Debug
Unity -quit -batchmode -projectPath /path/to/MyUnityProject \
  -executeMethod UnityKit.Editor.Build.ExportAndroidDebug

# Android Release
Unity -quit -batchmode -projectPath /path/to/MyUnityProject \
  -executeMethod UnityKit.Editor.Build.ExportAndroidRelease

# iOS Debug (must set -buildTarget iOS)
Unity -quit -batchmode -projectPath /path/to/MyUnityProject \
  -buildTarget iOS \
  -executeMethod UnityKit.Editor.Build.ExportIOSDebug

# iOS Release
Unity -quit -batchmode -projectPath /path/to/MyUnityProject \
  -buildTarget iOS \
  -executeMethod UnityKit.Editor.Build.ExportIOSRelease

# WebGL
Unity -quit -batchmode -projectPath /path/to/MyUnityProject \
  -executeMethod UnityKit.Editor.Build.ExportWebGL

Without UNITY_KIT_FLUTTER_PROJECT, artifacts stay in Builds/ as a standalone artifact — upload them from the Unity job and download them into the Flutter job:

.github/workflows/build.ymlyaml
# Example GitHub Actions workflow
unity-build:
  steps:
    - name: Export Android
      run: Unity -quit -batchmode ...
    - name: Upload artifact
      uses: actions/upload-artifact@v4
      with:
        name: unity-android
        path: MyUnityProject/Builds/android/unityLibrary/

flutter-build:
  needs: unity-build
  steps:
    - name: Download Unity artifact
      uses: actions/download-artifact@v4
      with:
        name: unity-android
        path: my_flutter_app/android/unityLibrary/
    - name: Build Flutter
      run: cd my_flutter_app && flutter build apk

Maintenance

When to re-export

An export is a compiled snapshot of your Unity project. Re-export (and redeploy, or let auto-deploy handle it) whenever an input to that snapshot changes:

TriggerAction
You changed Player Settings — e.g. enabling ARM64 after the Unity view was stuck on the placeholder on a 64-bit deviceRe-export and redeploy
You edited game scripts, scenes, or assets that ship inside the Unity playerRe-export so the compiled artifact reflects the change
You added a custom [Serializable] DTO used with JsonUtility.FromJson<T>()Add the type to link.xml, then re-export — IL2CPP stripping otherwise removes it
You hit NamedBuildTarget / Il2CppCodeGeneration compilation errors (Unity 6000+ APIs)Update to the latest Build.cs (it uses BuildTargetGroup for Unity 2022.3+), then re-export

Confirm on device, not just in the artifact

Whether the export worked is judged on a physical device — the Settings window only reports BUILT / -- per platform. After a re-export, redeploy and run the Flutter app (flutter pub get then flutter run) to confirm Unity actually loads.

Let's make something together.

If you have any questions about a new project or other inquiries, feel free to contact us. We will get back to you as soon as possible.

Codigee
We are using cookies. Learn more