Open sourceFlutter package
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).
- 100,000+ downloads
- MIT
- Unity 2022.3 LTS to Unity 6
DocsUnity export
Unity export guide
Install the UnityKit scripts, configure the build, and export library artifacts for Android, iOS and WebGL from the Flutter menu.
On this page8 sections
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
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).
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.
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 |
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".
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 apkWhen 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.
No overengineering. No wasted time. Just straight-up execution.
Or book a call with Eryk (opens the booking calendar)[email protected]


