This repository has been archived on 2020-08-22. You can view files and clone it, but cannot push or open issues or pull requests.
flutter-unity-view-widget/README.md

428 lines
19 KiB
Markdown
Raw Permalink Normal View History

2019-03-09 10:47:09 -05:00
# flutter_unity_widget
2019-08-02 05:15:33 -04:00
[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)
2019-03-09 10:47:09 -05:00
2019-03-27 03:30:12 -04:00
[![version][version-badge]][package]
[![MIT License][license-badge]][license]
[![PRs Welcome][prs-badge]](http://makeapullrequest.com)
[![Watch on GitHub][github-watch-badge]][github-watch]
[![Star on GitHub][github-star-badge]][github-star]
[![Gitter](https://badges.gitter.im/flutter-unity/community.svg)](https://gitter.im/flutter-unity/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Flutter unity 3D widget for embedding unity in flutter. Now you can make awesome gamified features of your app in Unity and get it rendered in a Flutter app both in fullscreen and embeddable mode. Works great on Android and iOS. There are now two unity app examples in the unity folder, one with the default scene and another based on Unity AR foundation samples.
<br />
<br />
Note: I have updated the example for Unity 2019.3.5 and there are some new changes in the scripts folder. Please replace your already copied files and folders in your unity project
2019-03-09 10:47:09 -05:00
2019-03-27 03:30:12 -04:00
## Installation
First depend on the library by adding this to your packages `pubspec.yaml`:
```yaml
dependencies:
2020-03-19 07:47:42 -04:00
flutter_unity_widget: ^0.1.6+8
2019-03-27 03:30:12 -04:00
```
Now inside your Dart code you can import it.
```dart
2019-03-29 02:44:00 -04:00
import 'package:flutter_unity_widget/flutter_unity_widget.dart';
2019-03-27 03:30:12 -04:00
```
2019-03-27 14:56:47 -04:00
<br />
2019-03-09 10:47:09 -05:00
2019-03-26 17:06:17 -04:00
## Preview
2019-03-09 10:47:09 -05:00
2019-08-02 04:47:31 -04:00
30 fps gifs, showcasing communication between Flutter and Unity:
![gif](https://github.com/snowballdigital/flutter-unity-view-widget/blob/master/preview_android.gif?raw=true)
2019-08-02 04:47:31 -04:00
![gif](https://github.com/snowballdigital/flutter-unity-view-widget/blob/master/preview_ios.gif?raw=true)
2019-03-28 14:05:38 -04:00
2019-03-27 14:56:47 -04:00
<br />
## Setup Project
For this, there is also a video tutorial, which you can find a [here](https://www.youtube.com/watch?v=exNPmv_7--Q).
2019-03-26 17:06:17 -04:00
### Add Unity Project
2019-03-29 02:46:23 -04:00
1. Create an unity project, Example: 'UnityDemoApp'.
2. Create a folder named `unity` in flutter project folder.
2019-03-27 03:30:12 -04:00
2. Move unity project folder to `unity` folder.
Now your project files should look like this.
```
.
├── android
├── ios
├── lib
├── test
├── unity
2019-03-29 02:46:23 -04:00
│ └── <Your Unity Project> // Example: UnityDemoApp
2019-03-27 03:30:12 -04:00
├── pubspec.yml
├── README.md
```
2019-03-26 17:06:17 -04:00
### Configure Player Settings
2019-03-27 03:30:12 -04:00
1. First Open Unity Project.
2019-03-26 17:06:17 -04:00
2019-08-01 07:13:20 -04:00
2. Click Menu: File => Build Settings
2019-03-26 17:06:17 -04:00
2019-08-01 07:13:20 -04:00
Be sure you have at least one scene added to your build.
3. => Player Settings
2019-03-27 03:30:12 -04:00
2019-03-27 14:56:47 -04:00
**Android Platform**:
1. Make sure your `Graphics APIs` are set to OpenGLES3 with a fallback to OpenGLES2 (no Vulkan)
2. Change `Scripting Backend` to IL2CPP.
2019-03-26 17:06:17 -04:00
3. Mark the following `Target Architectures` :
2019-03-27 14:56:47 -04:00
- ARMv7 ✅
- ARM64 ✅
2020-03-20 21:45:09 -04:00
- x86 ✅ (In Unity Version 2019.2+, this feature is not avaliable due to the lack of Unity Official Support)
2019-03-26 17:06:17 -04:00
2019-08-01 08:11:30 -04:00
<img src="https://raw.githubusercontent.com/snowballdigital/flutter-unity-view-widget/master/Screenshot%202019-03-27%2007.31.55.png" width="400" />
2019-03-26 17:06:17 -04:00
2019-08-01 07:13:20 -04:00
**iOS Platform**:
2019-08-01 08:11:30 -04:00
1. This only works with Unity version >=2019.3 because uses Unity as a library!
2019-08-02 07:05:41 -04:00
2. Depending on where you want to test or run your app, (simulator or physical device), you should select the appropriate SDK on `Target SDK`.
2019-03-27 14:56:47 -04:00
<br />
2019-03-29 04:05:49 -04:00
2019-03-27 14:56:47 -04:00
<br />
2019-03-27 03:30:12 -04:00
2019-03-26 17:06:17 -04:00
### Add Unity Build Scripts and Export
2020-03-27 07:53:30 -04:00
Copy [`Build.cs`](https://github.com/snowballdigital/flutter-unity-view-widget/tree/master/scripts/unity_2019_3_5_later/Editor/Build.cs) and [`XCodePostBuild.cs`](https://github.com/snowballdigital/flutter-unity-view-widget/tree/master/scripts/unity_2019_3_5_later/Editor/XCodePostBuild.cs) to `unity/<Your Unity Project>/Assets/Scripts/Editor/`
2019-03-27 03:30:12 -04:00
Open your unity project in Unity Editor. Now you can export the Unity project with `Flutter/Export Android` (for Unity versions up to 2019.2), `Flutter/Export Android (Unity 2019.3.*)` (for Unity versions 2019.3 and up, which uses the new [Unity as a Library](https://blogs.unity3d.com/2019/06/17/add-features-powered-by-unity-to-native-mobile-apps/) export format), or `Flutter/Export IOS` menu.
2019-03-28 14:05:38 -04:00
2019-03-27 15:01:55 -04:00
<img src="https://github.com/snowballdigital/flutter-unity-view-widget/blob/master/Screenshot%202019-03-27%2008.13.08.png?raw=true" width="400" />
2019-03-27 03:30:12 -04:00
Android will export unity project to `android/UnityExport`.
IOS will export unity project to `ios/UnityExport`.
2019-03-27 14:56:47 -04:00
<br />
**Android Platform Only**
1. After exporting the unity game, open Android Studio and and add the `Unity Classes` Java `.jar` file as a module to the unity project. You just need to do this once if you are exporting from the same version of Unity everytime. The `.jar` file is located in the ```<Your Flutter Project>/android/UnityExport/lib``` folder
2. Add the following to your ```<Your Flutter Project>/android/settings.gradle```file:
```gradle
include ":UnityExport"
project(":UnityExport").projectDir = file("./UnityExport")
```
3. If using Unity 2019.2 or older, open `build.gradle` of `UnityExport` module and replace the dependencies with
2019-03-27 14:56:47 -04:00
```gradle
dependencies {
implementation project(':unity-classes') // the unity classes module you added from step 1
2019-03-27 14:56:47 -04:00
}
```
2020-03-20 21:45:09 -04:00
4. To build a release package, you need to add signconfig in `UnityExport/build.gradle`. The code below use the `debug` signConfig for all buildTypes, which can be changed as you well if you need specify signConfig.
```
buildTypes {
release {
signingConfig signingConfigs.debug
}
debug {
signingConfig signingConfigs.debug
}
profile{
signingConfig signingConfigs.debug
}
innerTest {
//...
matchingFallbacks = ['debug', 'release']
}
}
```
5. If you found the duplicate app icons on your launcher after installing the app, you can just open `UnityExport` Manifest file and comment the codes below
```gradle
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false">
// <intent-filter>
// <action android:name="android.intent.action.MAIN" />
// <category android:name="android.intent.category.LAUNCHER" />
// <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
// </intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
```
2019-03-26 17:06:17 -04:00
2019-08-01 07:13:20 -04:00
**iOS Platform Only**
2019-08-01 08:11:30 -04:00
1. open your ios/Runner.xcworkspace (workspace!, not the project) in Xcode and add the exported project in the workspace root (with a right click in the Navigator, not on an item -> Add Files to “Runner” -> add the UnityExport/Unity-Iphone.xcodeproj file
<img src="workspace.png" width="400" />
2019-08-01 07:13:20 -04:00
2. Select the Unity-iPhone/Data folder and change the Target Membership for Data folder to UnityFramework
<img src="change_target_membership_data_folder.png" width="400" />
3. Add this to your Runner/Runner/Runner-Bridging-Header.h
2019-08-01 07:16:57 -04:00
```c
#import "UnityUtils.h"
```
4. Add to Runner/Runner/AppDelegate.swift before the GeneratedPluginRegistrant call:
2019-08-01 07:16:57 -04:00
```swift
InitArgs(CommandLine.argc, CommandLine.unsafeArgv)
```
Or when using Objective-C your `main.m` should look like this:
```
#import "UnityUtils.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
InitArgs(argc, argv);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
2019-08-01 07:16:57 -04:00
```
2019-08-01 07:13:20 -04:00
5. Opt-in to the embedded views preview by adding a boolean property to the app's `Info.plist` file with the key `io.flutter.embedded_views_preview` and the value `YES`.
6. Add UnityFramework.framework as a Library to the Runner project
<img src="libraries.png" width="400" />
2019-03-27 14:56:47 -04:00
<br />
2019-07-31 03:46:56 -04:00
### AR Foundation ( requires Unity 2019.3.*)
2019-10-18 10:10:18 -04:00
![gif](https://github.com/snowballdigital/flutter-unity-view-widget/blob/master/ar-demo.gif?raw=true)
2019-10-18 10:14:04 -04:00
Check out the Unity AR Foundation Samples [Demo Repository](https://github.com/juicycleff/flutter-unity-arkit-demo)
**The Demo Repository is not guaranteed to be up-to-date with the latest flutter-unity-view-widget master. Make sure to follow the steps listed below for setting up AR Foundation on iOS and Android in your projects.**
2019-10-22 07:23:04 -04:00
**iOS**
Go to target info list on Xcode and add this key and value;
key: `Privacy - Camera Usage Description` value: `$(PRODUCT_NAME) uses Cameras`
**Android**
2019-08-02 06:33:07 -04:00
2019-07-31 03:46:56 -04:00
If you want to use Unity for integrating Augmented Reality in your Flutter app, a few more changes are required:
1. Export the Unity Project as previously stated (using the Editor Build script).
2. Check if the exported project includes all required Unity libraries (.so) files (`lib/\<architecture\>/libUnityARCore.so` and `libarpresto_api.so`). There seems to be a bug where a Unity export does not include all lib files. If they are missing, use Unity to build a standalone .apk of your AR project, unzip the resulting apk, and copy over the missing .lib files to the `UnityExport` module.
3. Similar to how you've created the `unity-classes` module in Android Studio, create similar modules for all exported .aar and .jar files in the `UnityExport/libs` folder (`arcore_client.aar`, `unityandroidpermissions.aar`, `UnityARCore.aar`).
4. Update the build.gradle script of the `UnityExport` module to depend on the new modules (again, similar to how it depends on `unity-classes`).
5. Finally, update your Dart code build method where you include the `UnityWidget` and add `isARScene: true,`.
Sadly, this does have the side effect of making your Flutter activity act in full screen, as Unity requires control of your Activity for running in AR, and it makes several modifications to your Activity as a result (including setting it to full screen).
2019-03-27 14:56:47 -04:00
2019-03-26 17:06:17 -04:00
### Add UnityMessageManager Support
2019-03-27 14:56:47 -04:00
2020-03-27 07:53:30 -04:00
Copy [`UnityMessageManager.cs`](https://github.com/snowballdigital/flutter-unity-view-widget/tree/master/scripts/unity_2019_3_5_later/UnityMessageManager.cs) to your unity project.
2019-03-27 03:30:12 -04:00
2020-03-27 07:53:30 -04:00
Copy this folder [`JsonDotNet`](https://github.com/snowballdigital/flutter-unity-view-widget/tree/master/scripts/unity_2019_3_5_later/JsonDotNet) to your unity project.
2019-03-26 17:06:17 -04:00
2020-03-27 07:53:30 -04:00
Copy [`link.xml`](https://github.com/snowballdigital/flutter-unity-view-widget/tree/master/scripts/unity_2019_3_5_later/link.xml) to your unity project.
2019-03-26 17:06:17 -04:00
2020-03-27 07:53:30 -04:00
(2019.3.5* only) Copy this folder [`Plugins`](https://github.com/snowballdigital/flutter-unity-view-widget/tree/master/scripts/unity_2019_3_5_later/Plugins) to your unity project.
2019-03-27 14:56:47 -04:00
<br />
2019-03-27 03:30:12 -04:00
### Vuforia
**Android**
Similar to setting up AR Foundation, but creating a module for the VuforiaWrapper instead.
Thanks to [@PiotrxKolasinski](https://github.com/PiotrxKolasinski) for writing down the exact steps:
1. Change in build.gradle: `implementation(name: 'VuforiaWrapper', ext:'aar')` to `implementation project(':VuforiaWrapper')`
2. In settings.gradle in the first line at the end add: `':VuforiaWrapper'`
3. From menu: File -> New -> New Module choose "import .JAR/.AAR Package" and add lib VuforiaWrapper.arr. Move generated folder to android/
4. In Widget UnityWidget add field: `isARScene: true`
5. Your App need camera permission (you can set in settings on mobile)
2019-03-27 14:56:47 -04:00
## Examples
### Simple Example
2019-03-27 03:30:12 -04:00
2019-03-27 14:56:47 -04:00
```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';
class UnityDemoScreen extends StatefulWidget {
UnityDemoScreen({Key key}) : super(key: key);
@override
_UnityDemoScreenState createState() => _UnityDemoScreenState();
}
class _UnityDemoScreenState extends State<UnityDemoScreen>{
static final GlobalKey<ScaffoldState> _scaffoldKey =
GlobalKey<ScaffoldState>();
UnityWidgetController _unityWidgetController;
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: SafeArea(
bottom: false,
child: WillPopScope(
onWillPop: () {
// Pop the category page if Android back button is pressed.
},
child: Container(
color: colorYellow,
child: UnityWidget(
onUnityViewCreated: onUnityCreated,
),
),
),
),
);
}
// Callback that connects the created controller to the unity controller
2019-03-29 02:53:28 -04:00
void onUnityCreated(controller) {
this._unityWidgetController = controller;
2019-03-27 14:56:47 -04:00
}
}
```
<br />
### Communicating with and from Unity
```dart
import 'package:flutter/material.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';
2019-10-17 07:29:57 -04:00
void main() => runApp(MyApp());
2019-03-27 14:56:47 -04:00
2019-10-17 07:29:57 -04:00
class MyApp extends StatefulWidget {
2019-03-27 14:56:47 -04:00
@override
2019-10-17 07:29:57 -04:00
_MyAppState createState() => _MyAppState();
2019-03-27 14:56:47 -04:00
}
2019-10-17 07:29:57 -04:00
class _MyAppState extends State<MyApp> {
2019-03-27 14:56:47 -04:00
static final GlobalKey<ScaffoldState> _scaffoldKey =
GlobalKey<ScaffoldState>();
UnityWidgetController _unityWidgetController;
2019-10-17 07:29:57 -04:00
double _sliderValue = 0.0;
2019-03-27 14:56:47 -04:00
2019-10-17 07:29:57 -04:00
@override
void initState() {
super.initState();
}
2019-03-27 14:56:47 -04:00
2019-10-17 07:29:57 -04:00
@override
2019-03-27 14:56:47 -04:00
Widget build(BuildContext context) {
2019-10-17 07:29:57 -04:00
return MaterialApp(
home: Scaffold(
2019-03-29 02:53:28 -04:00
key: _scaffoldKey,
appBar: AppBar(
title: const Text('Unity Flutter Demo'),
),
2019-10-17 07:29:57 -04:00
body: Card(
margin: const EdgeInsets.all(8),
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Stack(
children: <Widget>[
UnityWidget(
onUnityViewCreated: onUnityCreated,
isARScene: false,
onUnityMessage: onUnityMessage,
2019-03-29 02:53:28 -04:00
),
2019-10-17 07:29:57 -04:00
Positioned(
bottom: 20,
left: 20,
right: 20,
child: Card(
elevation: 10,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text("Rotation speed:"),
),
Slider(
onChanged: (value) {
setState(() {
_sliderValue = value;
});
setRotationSpeed(value.toString());
},
value: _sliderValue,
min: 0,
max: 20,
),
],
),
),
),
],
),
),
2019-03-27 14:56:47 -04:00
),
);
}
2019-10-17 07:29:57 -04:00
// Communcation from Flutter to Unity
void setRotationSpeed(String speed) {
_unityWidgetController.postMessage(
'Cube',
'SetRotationSpeed',
speed,
);
}
// Communication from Unity to Flutter
void onUnityMessage(controller, message) {
print('Received message from unity: ${message.toString()}');
}
2019-03-27 14:56:47 -04:00
// Callback that connects the created controller to the unity controller
2019-03-29 02:53:28 -04:00
void onUnityCreated(controller) {
this._unityWidgetController = controller;
2019-03-27 14:56:47 -04:00
}
}
```
2019-03-27 03:30:12 -04:00
2019-03-29 04:05:49 -04:00
## API
2019-08-01 04:32:36 -04:00
- `pause()` (Use this to pause unity player)
- `resume()` (Use this to resume unity player)
2019-08-05 08:06:51 -04:00
- `postMessage(String gameObject, methodName, message)` (Allows you invoke commands in Unity from flutter)
2019-08-05 08:08:49 -04:00
- `onUnityMessage(data)` (Unity to flutter bindding and listener)
2019-03-29 04:05:49 -04:00
2019-07-31 03:46:56 -04:00
## Known issues
- Android Export requires several manual changes
- Using AR will make the activity run in full screen (hiding status and navigation bar).
2019-03-27 03:30:12 -04:00
[version-badge]: https://img.shields.io/pub/v/flutter_unity_widget.svg?style=flat-square
2019-08-02 03:42:55 -04:00
[package]: https://pub.dartlang.org/packages/flutter_unity_widget/
2019-03-27 03:30:12 -04:00
[license-badge]: https://img.shields.io/github/license/snowballdigital/flutter-unity-view-widget.svg?style=flat-square
[license]: https://github.com/snowballdigital/flutter-unity-view-widget/blob/master/LICENSE
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com
[github-watch-badge]: https://img.shields.io/github/watchers/snowballdigital/flutter-unity-view-widget.svg?style=social
[github-watch]: https://github.com/snowballdigital/flutter-unity-view-widget/watchers
[github-star-badge]: https://img.shields.io/github/stars/snowballdigital/flutter-unity-view-widget.svg?style=social
[github-star]: https://github.com/snowballdigital/flutter-unity-view-widget/stargazers
2019-08-02 04:45:10 -04:00
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
2019-08-12 05:51:52 -04:00
<td align="center"><a href="https://www.xraph.com"><img src="https://avatars2.githubusercontent.com/u/11243590?v=4" width="100px;" alt="Rex Raphael"/><br /><sub><b>Rex Raphael</b></sub></a><br /><a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=juicycleff" title="Code">💻</a> <a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=juicycleff" title="Documentation">📖</a> <a href="#question-juicycleff" title="Answering Questions">💬</a> <a href="https://github.com/snowballdigital/flutter-unity-view-widget/issues?q=author%3Ajuicycleff" title="Bug reports">🐛</a> <a href="#review-juicycleff" title="Reviewed Pull Requests">👀</a> <a href="#tutorial-juicycleff" title="Tutorials"></a></td>
2019-08-02 08:22:13 -04:00
<td align="center"><a href="https://stockxit.com"><img src="https://avatars1.githubusercontent.com/u/1475368?v=4" width="100px;" alt="Thomas Stockx"/><br /><sub><b>Thomas Stockx</b></sub></a><br /><a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=thomas-stockx" title="Code">💻</a> <a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=thomas-stockx" title="Documentation">📖</a> <a href="#question-thomas-stockx" title="Answering Questions">💬</a> <a href="#tutorial-thomas-stockx" title="Tutorials"></a></td>
2019-08-02 05:40:14 -04:00
<td align="center"><a href="http://krispypen.github.io/"><img src="https://avatars1.githubusercontent.com/u/156955?v=4" width="100px;" alt="Kris Pypen"/><br /><sub><b>Kris Pypen</b></sub></a><br /><a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=krispypen" title="Code">💻</a> <a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=krispypen" title="Documentation">📖</a> <a href="#question-krispypen" title="Answering Questions">💬</a> <a href="#tutorial-krispypen" title="Tutorials"></a></td>
<td align="center"><a href="https://github.com/lorant-csonka-planorama"><img src="https://avatars2.githubusercontent.com/u/48209860?v=4" width="100px;" alt="Lorant Csonka"/><br /><sub><b>Lorant Csonka</b></sub></a><br /><a href="https://github.com/snowballdigital/flutter-unity-view-widget/commits?author=lorant-csonka-planorama" title="Documentation">📖</a> <a href="#video-lorant-csonka-planorama" title="Videos">📹</a></td>
2019-08-02 04:45:10 -04:00
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
2019-08-02 06:28:48 -04:00
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!