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 ReactUnityAppyarn add @brice-gros/react-native-unity-viewSince 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}.xcworkspaceand add the exported project(ios/unityLibrary/Unity-Iphone.xcodeproj) to the workspace root
- Select the
Unity-iPhone/Datafolder and change the Target Membership to UnityFramework
- Add
UnityFramework.frameworkas 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 Nameto the name of your Xcode project. (ios/${XcodeProjectName}.xcodeproj)
Under Other Settings make sure:
Scripting Backendis set toIL2CPPApi Compatibility Levelis.NET Standard 2.0- under
Target Architectures,ARM64andARMv7are 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.propertiesfile from the Unity build folder will be added in your react native project asandroid/local.propertiesunless 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 --licensesAlso, since Gradle version >7, React Native project's
android/build.gradlecontains andkVersionentry which can be incompatible with thesdk.dirandndk.dirdefined bylocal.properties. In that case, either change it to match thendkVersionfrom the NDK atndk.dir, or comment out both lines forsdk.dirandndk.dirinlocal.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.
gameObjectThe Name of GameObject. Also can be a path string.methodNameMethod name in GameObject instance.messageThe 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.
messageThe 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





