@brice-gros/react-native-unity-view v0.0.3
react-native-unity-view
Integrate unity3d within a React Native app. Add a react native component to show unity. Works on Android (TODO on iOS)
Notice
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
Requirements
- Unity 2020.3+
- Nodejs 16.14+
- React Native 0.63
Prerequisites
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
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
Install
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.
Configure Native Build
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.
Android Build
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
iOS build (TODO)
- 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]));
}
}
Configuring Unity
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
Add Unity package
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+
Add Unity scripts
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
Player Settings
- 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
)
◼️ Additional changes for Android Settings
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
◼️ Additional changes for iOS Settings (TODO)
Under Other Settings
make sure Auto Graphics API
is checked.
Export From Unity
To export, open the Build Settings
window (File
> Build Settings...
).
💡 For a Development
build with Script Debugging
enabled, tick the corresponding boxes as usual.
⚠️ Don't use the 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, depending upon Gradle version, React Native project's
android/build.gradle
can contain andkVersion
entry which is 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 both lines forsdk.dir
andndk.dir
inlocal.properties
.
Use in React Native
UnityView Props
onMessage
Receive message from Unity
Make sure you have added UnityMessageManager
Example:
- 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>
);
}
onUnityMessage
RecommendedReceive 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>
);
}
UnityModule
import { UnityModule } from '@brice-gros/react-native-unity-view';
isReady(): Promise<boolean>
Return whether is unity ready.
createUnity(): Promise<boolean>
Manual init the Unity. Usually Unity is auto created when the first view is added.
postMessage(gameObject: string, methodName: string, message: string)
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>
);
}
postMessageToUnityManager(message: string | UnityViewMessage)
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>
);
}
addMessageListener(listener: (message: string | MessageHandler) => void): number
Receive string and json message from unity.
addStringMessageListener(listener: (message: string) => void): number
Only receive string message from unity.
addUnityMessageListener(listener: (handler: MessageHandler) => void): number
Only receive json message from unity.
pause()
Pause the unity player.
resume()
Resume the unity player.
Example Code
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