Integrate unity3d within a React Native app. Add a react native component to show unity. Works on Android (TODO on iOS)
This is a fork of asmadsen/react-native-unity-view to make it work with node 16 LTS, React Native >= 0.63 and Unity 2020.3 LTS
This project may or may not be updated depending on the further use of it, feel free to fork it
- Unity 2020.3+
- Nodejs 16.14+
- React Native 0.63
Before anything, a React-Native app is needed, but beware, do not use Expo
nor create-react-native-app
which uses Expo
or you'll have to eject it
choco install nvm # for windows only
nvm install 16.14.0
nvm use 16.14.0
npm install yarn
yarn install react-native
npx react-native init ReactUnityApp --template react-native-template-typescript
cd ReactUnityApp
yarn add @brice-gros/react-native-unity-view
Since this project uses the exported data from Unity you will have more configuration steps than a normal React Native module.
For the react native project to recognize the unityLibrary
folder which will contain the Unity exported project, some changes as to be done for each platform.
To have gradle working properly, some modifications has to be done to the react native project:
- Add the following to the
android/build.gradle
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
So it looks like this
// [..]
allprojects {
repositories {
// [..]
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
- Add these two lines to
android/settings.gradle
include ":unityLibrary"
project(":unityLibrary").projectDir = new File(rootProject.projectDir, './unityLibrary')
- Add this line to
gradle.properties
:
unityStreamingAssets=.unity3d
- Open your
ios/{PRODUCT_NAME}.xcworkspace
and add the exported project(ios/unityLibrary/Unity-Iphone.xcodeproj
) to the workspace root
- Select the
Unity-iPhone/Data
folder and change the Target Membership to UnityFramework
- Add
UnityFramework.framework
as a library to your Project
- Modify
main.m
#import "UnityUtils.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
InitArgs(argc, argv);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
To configure Unity to add the exported files to your app we use some build scripts. And the default configuration expects that you place your Unity Project in the following position relative to our app.
.
├── android
├── ios
├── unity
│ └── <Your Unity Project> // Example: Cube
├── node_modules
├── package.json
└── README.md
From the package manager menu (Window
> Package Manager
), select from the left corner Add package from git URL
, and enter com.unity.nuget.newtonsoft-json
and be sure to use version 3.0.1+
Copy template scripts to your project:
cp -r node_modules/@brice-gros/react-native-unity-view/template/* ./unity/YourProject/
This will add:
- Build.cs, controlling the build from the editor
- XCodePostBuild.cs, used for ios (TODO)
- UnityMessageManager.cs, a script managing the messages between React Native and Unity
- Rotate.cs, a MonoBehavior sample script rotating a game object controllable from react native, and sending back a message to react native
- Open your Unity Project
- Go to Player settings (File => Build Settings => Player Settings)
- Change
Product Name
to the name of your Xcode project. (ios/${XcodeProjectName}.xcodeproj
)
Under Other Settings
make sure:
Scripting Backend
is set toIL2CPP
Api Compatibility Level
is.NET Standard 2.0
- under
Target Architectures
,ARM64
andARMv7
are checked
Under Other Settings
make sure Auto Graphics API
is checked.
To export, open the Build Settings
window (File
> Build Settings...
).
💡 For a Development
build with Script Debugging
enabled, tick the corresponding boxes as usual.
Build
or Export
button, and note that using Switch platform
is not required
👉 But export the Unity Project using ReactNative => Export Android
(TODO or ReactNative => Export IOS
).
Then the exported artifacts will be placed in a folder called unityLibrary
inside either the android
or ios
folder.
🛠️ ANDROID KNOWN ISSUES:
On Android, the
local.properties
file from the Unity build folder will be added in your react native project asandroid/local.properties
unless it already exists.An error message can require you to accept Android sdk manager licenses on the first Android build, this can be done using the following commandline:
# From the directory specified by `sdk.dir` in local.properties, run: ./tools/bin/sdkmanager.bat --licenses
Also, since Gradle version >7, React Native project's
android/build.gradle
contains andkVersion
entry which can be incompatible with thesdk.dir
andndk.dir
defined bylocal.properties
. In that case, either change it to match thendkVersion
from the NDK atndk.dir
, or comment out both lines forsdk.dir
andndk.dir
inlocal.properties
.
Receive message from Unity
Make sure you have added UnityMessageManager
- Send message from Unity
UnityMessageManager.Instance.SendMessageToRN("click");
- Receive message in React Native
onMessage(event) {
console.log('OnUnityMessage: ' + event.nativeEvent.message); // OnUnityMessage: click
}
render() {
return (
<View style={[styles.container]}>
<UnityView
style={style.unity}
onMessage={this.onMessage.bind(this)}
/>
</View>
);
}
[Recommended]Receive json message from unity.
onUnityMessage(handler) {
console.log(handler.name); // the message name
console.log(handler.data); // the message data
setTimeout(() => {
// You can also create a callback to Unity.
handler.send('I am callback!');
}, 2000);
}
render() {
return (
<View style={[styles.container]}>
<UnityView
style={style.unity}
onUnityMessage={this.onMessage.bind(this)}
/>
</View>
);
}
import { UnityModule } from '@brice-gros/react-native-unity-view';
Return whether is unity ready.
Manual init the Unity. Usually Unity is auto created when the first view is added.
Send message to unity.
gameObject
The Name of GameObject. Also can be a path string.methodName
Method name in GameObject instance.message
The message will post.
Example:
- Add a message handle method in
MonoBehaviour
.
public class Rotate : MonoBehaviour {
void handleMessage(string message) {
Debug.Log("onMessage:" + message);
}
}
-
Add Unity component to a GameObject.
-
Send message use javascript.
onToggleRotate() {
if (this.unity) {
// gameobject param also can be 'Cube'.
UnityModule.postMessage('GameObject/Cube', 'toggleRotate', 'message');
}
}
render() {
return (
<View style={[styles.container]}>
<UnityView
ref={(ref) => this.unity = ref}
style={style.unity}
/>
<Button label="Toggle Rotate" onPress={this.onToggleRotate.bind(this)} />
</View>
);
}
Send message to UnityMessageManager
.
Please copy UnityMessageManager.cs
to your unity project and rebuild first.
Same to postMessage('UnityMessageManager', 'onMessage', message)
This is recommended to use.
message
The message will post.
Example:
- Add a message handle method in C#.
void Awake()
{
UnityMessageManager.Instance.OnMessage += toggleRotate;
}
void onDestroy()
{
UnityMessageManager.Instance.OnMessage -= toggleRotate;
}
void toggleRotate(string message)
{
Debug.Log("onMessage:" + message);
canRotate = !canRotate;
}
- Send message use javascript.
onToggleRotate() {
UnityModule.postMessageToUnityManager('message');
}
render() {
return (
<View style={[styles.container]}>
<UnityView
ref={(ref) => this.unity = ref}
style={style.unity}
/>
<Button label="Toggle Rotate" onPress={this.onToggleRotate.bind(this)} />
</View>
);
}
Receive string and json message from unity.
Only receive string message from unity.
Only receive json message from unity.
Pause the unity player.
Resume the unity player.
import React from 'react';
import { StyleSheet, View } from 'react-native';
import UnityView from '@brice-gros/react-native-unity-view';
export default class App extends React.Component {
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<UnityView style={{ flex: 1 }}/>
</View>
</View>
);
}
}
See github repository for a complete example