To begin, create a new Flutter project and add a "unity" folder. Once done, create a new Unity project and set the path to the "unity" folder you just created. Your Flutter and Unity project should look like this:
📦flutter_unity_sample -> Flutter Project
┣ 📂android
┣ 📂ios
┣ 📂lib
┃ ┗ 📜main.dart
┣ 📂test
┣ 📂unity
┃ ┗ 📂sample_game -> Unity Project
┣ 📜README.md
┣ 📜analysis_options.yaml
┣ 📜flutter_unity_sample.iml
┣ 📜pubspec.lock
┗ 📜pubspec.yaml
In order to Flutter to work with Unity you'll need two components: the flutter_unity_widget package for Flutter and the fuw-(version).unitypackage for Unity.
flutter pub add flutter_unity_widget
which should install the latest version.Now that we have all the packages installed, we will make a small test and export/build the project to Flutter to know if everything work properly. You will rotate a cube as a test.
To test, we need to add some components to Unity. Add a cube game object in your editor then in the cube inspector you will add a "Unity Message Manager" script along with your own "RotateCube" script.
This is the code in Unity for the cube:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FlutterUnityIntegration; //import library code
public class RotateCube : MonoBehaviour
{
// this will help us send message to Flutter
private UnityMessageManager unityMessageManganer;
private float rotateSpeed = 0;
// Start is called before the first frame update
void Start()
{
unityMessageManganer = GetComponent<UnityMessageManager>();
}
// Update is called once per frame
void Update()
{
transform.Rotate(Vector3.up * Time.deltaTime * rotateSpeed);
//send to flutter deltaTime
unityMessageManganer.SendMessageToFlutter($"DeltaTime: {Time.deltaTime}");
}
// this is a method we created that we will call from Flutter to invoke
public void MoveCubeFromFlutter(string value){
rotateSpeed = float.Parse(value);
}
}
This is code in the Flutter side:
import 'package:flutter/material.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Unity Demo',
theme: ThemeData(
sliderTheme: const SliderThemeData(
showValueIndicator: ShowValueIndicator.always),
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Unity Sample'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late UnityWidgetController _unityWidgetController;
double sliderValue = 0;
void _updateSliderValue(double value) {
setState(() {
sliderValue = value;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Stack(
children: [
UnityWidget(
onUnityCreated: onUnityCreated,
onUnityMessage: onUnityMessage,
),
Positioned(
bottom: 64,
left: 16,
right: 16,
child: SizedBox(
height: 64,
width: MediaQuery.of(context).size.width,
child: Card(
margin: const EdgeInsets.all(8.0),
child: Slider(
label: sliderValue.round().toString(),
min: 0,
max: 200,
onChanged: (value) => moveCubeFromFlutter('$value'),
value: sliderValue,
),
),
),
)
],
),
),
);
}
// Communcation from Flutter to Unity
void moveCubeFromFlutter(String speed) {
_unityWidgetController.postMessage(
'Cube', //gameObjectName
'MoveCubeFromFlutter', // methodName
speed,
);
// update slider ui
_updateSliderValue(double.parse(speed));
}
// Communication from Unity to Flutter
// you should see the message of the deltaTime in the debug logs
void onUnityMessage(message) {
debugPrint('Received message from unity: ${message.toString()}');
}
// Callback that connects the created controller to the unity controller
void onUnityCreated(controller) {
_unityWidgetController = controller;
}
}
Now that your code is ready, you can export the build. Save your Unity Scene, then go to the Flutter menu item and select "Export Android (Release)". When the build is done loading, go to the Flutter counterpart in VSCode. Look for your gradle file in android/app/build.gradle
and change the line minSdkVersion flutter.minSdkVersion
to minSdkVersion 22
.
Run the code in your smartphone. You should be able to change the rotation of the cube with the slider widget. You should also see in the logs the Time.detlaTime
value that Unity is sending to Flutter.
You completed the codelab, you can now use your newly acquired knowledge to build astounding game to Flutter.
If you have trouble running the app, you can compare your code from the github repository.
This codelab may have some issues and to me this is only a draft, they are improvements that can be done. If you found a problem or have suggestions, you can click the report a mistake
on the bottom left of the codelab. It will open a github issue.