Skip to content
James Allen edited this page Sep 26, 2023 · 10 revisions

Notes for contributors

This plugin was designed as a federated plugin to make it easier to support multiple versions of Unity. Instead of having confusing branching code for different versions of Unity, and cases where fixing a problem with one version of Unity will break another, the idea is to create separate sub-packages which can be maintained and updated separately.

This plugin is organised as follows:

  • flutter_embed_unity: this is the main app-facing package, which you should depend on in your Flutter app's pubspec.yaml
  • flutter_embed_unity_2022_3_android: the Android platform package for this plugin, supporting Unity 2022.3 LTS
  • flutter_embed_unity_2022_3_ios: the iOS platform package for this plugin, supporting Unity 2022.3 LTS
  • flutter_embed_unity_platform_interface: The package that glues the app-facing package to the platform package(s). This package declares an interface that any platform package must implement to support the app-facing package. Having a single package that defines this interface ensures that all platform packages implement the same functionality in a uniform way.
  • example_unity_2022_3_project: a Unity project for building into the example project, for demo and development purposes

For example, if you wanted to support Unity 2019.4 on Android, you would create a separate package called flutter_embed_unity_2019_4_android by copying the flutter_embed_unity_2022_3_android and making changes as required (it would be best to keep the structure as similar as possible to help maintainability by other contributors).

A separate example Unity project for that version of Unity should also be created at the root of the repository to be used in the example app.

The pubspec.yaml for the public facing package defines which packages are currently the default 'endorsed' package, for example:

flutter:
  plugin:
    platforms:
      android:
        default_package: flutter_embed_unity_2022_3_android
      ios:
        default_package: flutter_embed_unity_2022_3_ios

The user can choose to use flutter_embed_unity_2019_4_android instead by depending on it directly it in their app's pubspec.yaml. Alternatively, for newer LTS versions of Unity, the default endorsed package could be updated as a breaking change.

Running the examples

The best way to get started with development is to run the example first.

There are 3 example projects: one for the app-facing package, which will run on both iOS and Android (flutter_embed_unity/flutter_embed_unity/example), one for the Android platform implementation package (flutter_embed_unity/flutter_embed_unity_2022_3_android/example) and one for the iOS platform implementation package (flutter_embed_unity/flutter_embed_unity_2022_3_ios/example).

If you just want to test the example, use the public facing package example.

If you want to do development on the plugin, you should use the platform implementation examples, because this will allow you to more easily edit the source code in Android Studio / xcode etc. with code completion, compiler warnings etc.

Preparing the examples for plugin development

  • Checkout the repository
  • Create a folder called unityLibrary at:
    • flutter_embed_unity/flutter_embed_unity_2022_3_android/example/android/unityLibrary for Android or
    • flutter_embed_unity/flutter_embed_unity_2022_3_ios/example/ios/unityLibrary for iOS
  • Install Unity 2022.3 LTS
  • Open the example Unity project
  • In Unity, go to Flutter Embed -> Export project to Flutter app (iOS or Android), and choose the export folder you created earlier
  • For iOS: In project navigator, expand the Unity-iPhone project, and select the Data folder. In the Inspector, under Target Membership, change the target membership to UnityFramework. Then select the Unity-iPhone project, then in the editor select the Unity-iPhone project under PROJECTS, then select the Build Settings tab. In the Build Settings tab, find the 'Other linker Flags' setting (you can use the search box to help you find it). Add the following : '-Wl,-U,_FlutterEmbedUnityIos_sendToFlutter'

Changing dependencies to local paths

The examples can now be run. However, any local changes you make to plugin source code will not be picked up by the examples, because they depend on published versions. Therefore if you want to work on the plugin and use the examples to test changes, you need to change the dependencies to local paths.

For Android, change flutter_embed_unity/flutter_embed_unity_2022_3_android/example/pubspec.yaml:

dependencies:
  ...
  flutter_embed_unity_2022_3_android: 
    path: ../
  flutter_embed_unity:
    path: ../../flutter_embed_unity

For iOS, change flutter_embed_unity/flutter_embed_unity_2022_3_ios/example/pubspec.yaml:

dependencies:
  ...
  flutter_embed_unity_2022_3_ios: 
    path: ../
  flutter_embed_unity:
    path: ../../flutter_embed_unity

Now to resolve a dependency conflict with local paths and published versions you also need to change flutter_embed_unity/flutter_embed_unity/pubspec.yaml:

dependencies:
  ...
  flutter_embed_unity_2022_3_android: 
    path: ../flutter_embed_unity_2022_3_android
  flutter_embed_unity_2022_3_ios:
    path: ../flutter_embed_unity_2022_3_ios

Develop the plugin

Now you should be able to develop the plugin platform source code, and use the platform example projects to test your changes.

On Android Studio, open flutter_embed_unity/flutter_embed_unity_2022_3_android Flutter project, then open one of the Kotlin files under the android subfolder, then click on "Open for editing in Android Studio" at the top right (or go to Tools -> Flutter -> Open for editing in Android Studio). This should open the Android subproject, with the example project also in the source navigator so it can compile correctly.

In Xcode, open flutter_embed_unity/flutter_embed_unity_2022_3_ios/example/ios/Runner.xcworkspace, then in the project navigator go to Pods/Development Pods/hello/../../example/ios/.symlinks/plugins/flutter_embed_unity to find the plugin Swift files.

Developer notes

Unity classes .jar

The Android package contains a JAR file in flutter_embed_unity\flutter_embed_unity_2022_3_android\android\libs containing bits of Unity code for Android such as the UnityPlayer which basically runs Unity. This was copied from the Unity editor install folder, for example at Unity Editors\2022.3.7f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes, and renamed to make it clear which version of Unity it is from.

It is included in the Android plugin project via a dependency in flutter_embed_unity\flutter_embed_unity_2022_3_android\android\build.gradle:

compileOnly fileTree(dir: 'libs', include: ['*.jar'])

To develop for a different version of Unity, make sure to replace this file!

UnityFramework.framework

The iOS package contains a framework file at flutter_embed_unity\flutter_embed_unity_2022_3_ios\ios\UnityFramework.framework, which is required for the plugin to build and for import UnityFramework to work. Without this you will get No such module UnityFramework. It was extracted from the
DerivedData folder after building the launcher Xcode project which Unity exports.

It is included into the iOS plugin build by adding this to flutter_embed_unity_2022_3_ios/ios/flutter_embed_unity_ios.podspec:

# Add UnityFramework
s.vendored_frameworks = 'UnityFramework.framework'

Then run pod install from flutter_embed_unity_2022_3_ios/example/iOS

To develop for a different version of Unity, make sure to rebuild UnityFramework!

-Wl,-U,_FlutterEmbedUnityIos_sendToFlutter

This is a slight hack borrowed from https://pub.dev/packages/flutter_unity which allows us to easily send messages from Unity to Flutter without having to mess around with manually editing Unity files.

-Wl allows us to pass additional options to the linker (ld) when it is invoked -U tells the linker to force the symbol _FlutterEmbedUnityIos_sendToFlutter to be entered in the output file as an undefined symbol. It will be linked instead to a C function defined in flutter_embed_unity_2022_3_ios/ios/Classes/SendToFlutter.swift

See the linker documentation for more

Resources

The following may be useful for plugin developers