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).
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.mdBefore 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.
| Requirement | Version |
|---|---|
| Unity Editor | 2022.3 LTS or newer |
| Flutter | 3.0+ |
| unity_kit | Added as a dependency in pubspec.yaml |
| Android SDK | API 24+ (for Android export) |
| Xcode | 14+ (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/
+-- 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 preservationCopy 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).
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.
| Platform | Switch platform | Export | Output folder |
|---|---|---|---|
| Android | File ▸ Build Settings ▸ Android ▸ Switch Platform | Flutter ▸ Export Android (Debug / Release) | <unity-project>/Builds/android/unityLibrary/ |
| iOS | File ▸ Build Settings ▸ iOS ▸ Switch Platform (wait for reimport) | Flutter ▸ Export iOS (Debug / Release) | <unity-project>/Builds/ios/UnityLibrary/ |
| WebGL | File ▸ Build Settings ▸ WebGL ▸ Switch Platform | Flutter ▸ 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)
| # | What | Why |
|---|---|---|
| 1 | com.android.application → com.android.library | Unity exports as an app; Flutter needs a library module |
| 2 | Remove applicationId | Libraries do not have their own app ID |
| 3 | Add namespace 'com.unity3d.player' | Required by Android Gradle Plugin 8+ |
| 4 | Comment out ndkPath | Conflicts with Flutter's NDK configuration |
| 5 | Fix ../shared/ → ./shared/ | Unity 6 shared folder path correction |
| 6 | Replace fileTree → unity-classes jar | Correct dependency for library mode |
| 7 | Strip <activity> from the manifest | Flutter hosts the activity, not Unity |
| 8 | Add ProGuard keep rules | Preserve com.unity_kit.** and com.unity3d.player.** from stripping |
| 9 | Add game_view_content_description string | Accessibility content description |
Android — deploy-only Gradle wiring (steps 10–12)
| # | What | Why |
|---|---|---|
| 10 | Add include ':unityLibrary' to settings.gradle | Register the Unity module in the Flutter project |
| 11 | Add a flatDir repository | Resolve unity-classes.jar |
| 12 | Add implementation project(':unityLibrary') to app/build.gradle | Wire 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 DSL | Kotlin 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:
-keep class com.unity_kit.** { *; }
-keep class com.unity3d.player.** { *; }iOS post-processing (XCodePostBuild)
| # | What | Why |
|---|---|---|
| 1 | Inject UnityReady NSNotification in startUnity: | The unity_kit iOS plugin observes this to know Unity is ready |
| 2 | Set SKIP_INSTALL = YES on the UnityFramework target | Required for framework builds |
| 3 | Set ENABLE_BITCODE = NO on the project | Bitcode is deprecated |
| 4 | Add a Data folder reference to UnityFramework | Required 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
Open Flutter ▸ Settings (Ctrl+Alt+S).
- 2
Set the Flutter project path (Browse or paste).
- 3
Click Save Flutter Project Path.
- 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:
| Priority | Source | Example |
|---|---|---|
| 1 (highest) | UNITY_KIT_FLUTTER_PROJECT env var | export UNITY_KIT_FLUTTER_PROJECT=/path/to/app |
| 2 | EditorPrefs (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)
| Section | Description |
|---|---|
| Build Artifacts | Shows the path and build status (BUILT / --) for each platform |
| Flutter Project | Optional path to the Flutter project; checks for pubspec.yaml |
| Quick Export | Buttons for every export variant |
| Deploy to Flutter Project | Copy the existing artifacts to the configured Flutter project |
| Clean All Builds | Delete 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.
# 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.ExportWebGLWithout 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:
# 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 apkMaintenance
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:
| Trigger | Action |
|---|---|
| You changed Player Settings — e.g. enabling ARM64 after the Unity view was stuck on the placeholder on a 64-bit device | Re-export and redeploy |
| You edited game scripts, scenes, or assets that ship inside the Unity player | Re-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.
