0.0.3 • Published 2 years ago

@brice-gros/react-native-unity-view v0.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

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:

  1. 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"
        }
    }
}
  1. Add these two lines to android/settings.gradle
include ":unityLibrary"
project(":unityLibrary").projectDir = new File(rootProject.projectDir, './unityLibrary')
  1. Add this line to gradle.properties:
unityStreamingAssets=.unity3d

iOS build (TODO)

  1. Open your ios/{PRODUCT_NAME}.xcworkspace and add the exported project(ios/unityLibrary/Unity-Iphone.xcodeproj) to the workspace root

Add unity ios project to ReactNative Ios workspace

  1. Select the Unity-iPhone/Data folder and change the Target Membership to UnityFramework

Set Target Membership of Data folder to UnityFramework

  1. Add UnityFramework.framework as a library to your Project

Add UnityFramework to project

  1. 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

  1. Open your Unity Project
  2. Go to Player settings (File => Build Settings => Player Settings)
  3. 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 to IL2CPP
  • Api Compatibility Level is .NET Standard 2.0
  • under Target Architectures, ARM64 and ARMv7 are checked

Android Configruation

◼️ Additional changes for iOS Settings (TODO)

Under Other Settings make sure Auto Graphics API is checked.

Player settings for iOS

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).

Build dropdown

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 as android/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 a ndkVersion entry which is incompatible with the sdk.dir and ndk.dir defined by local.properties. In that case, either change it to match the ndkVersion from the NDK at ndk.dir, or comment both lines for sdk.dir and ndk.dir in local.properties.

Use in React Native

UnityView Props

onMessage

Receive message from Unity

Make sure you have added UnityMessageManager

Example:

  1. Send message from Unity
UnityMessageManager.Instance.SendMessageToRN("click");
  1. 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:

  1. Add a message handle method in MonoBehaviour.
public class Rotate : MonoBehaviour {
    void handleMessage(string message) {
		Debug.Log("onMessage:" + message);
	}
}
  1. Add Unity component to a GameObject.

  2. 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:

  1. 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;
}
  1. 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