# @brice-gros/react-native-unity-view

> Embed Unity Player 2020.3 inside a React Native 0.63 / Node 16 LTS app

Latest version **0.0.3** (published 2022-03-02) · MIT license · 0 weekly downloads

## Install

```sh
npm install @brice-gros/react-native-unity-view
pnpm add @brice-gros/react-native-unity-view
yarn add @brice-gros/react-native-unity-view
bun add @brice-gros/react-native-unity-view
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.0.3 |
| Published | 2022-03-02 |
| First published | 2022-03-02 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 173.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | Brice Gros |
| Maintainers | brice-gros |
| Keywords | react-native, ios, android |

## Links

- npm: https://www.npmjs.com/package/@brice-gros/react-native-unity-view
- Repository: https://github.com/brice-gros/react-native-unity-view
- Homepage: https://github.com/brice-gros/react-native-unity-view#readme
- Issues: https://github.com/brice-gros/react-native-unity-view/issues
- npm.io page: https://npm.io/package/@brice-gros/react-native-unity-view

## Alternatives

- [@sindresorhus/slugify](https://npm.io/package/@sindresorhus/slugify.md) — 3.7M weekly downloads
- [solid-js](https://npm.io/package/solid-js.md) — 2.7M weekly downloads
- [expo-glass-effect](https://npm.io/package/expo-glass-effect.md) — 2.5M weekly downloads
- [nanoassert](https://npm.io/package/nanoassert.md) — 780.8K weekly downloads
- [@ffmpeg/ffmpeg](https://npm.io/package/@ffmpeg/ffmpeg.md) — 529.5K weekly downloads

## Recent versions

- 0.0.3 (latest) — 2022-03-02
- 0.0.2 — 2022-03-02

## README

# 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](https://github.com/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

```bash
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

```bash
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"
        }
    }
}
```

2. Add these two lines to `android/settings.gradle`

```
include ":unityLibrary"
project(":unityLibrary").projectDir = new File(rootProject.projectDir, './unityLibrary')
```

3. 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](docs/ios-add-unity-project.png)

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

![Set Target Membership of Data folder to UnityFramework](docs/ios-set-target-membership.png)

3. Add `UnityFramework.framework` as a library to your Project

![Add UnityFramework to project](docs/ios-add-unityframework.png)

4. Modify `main.m`

```objectivec
#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:
```bash
cp -r node_modules/@brice-gros/react-native-unity-view/template/* ./unity/YourProject/
```
This will add:
 - [Build.cs](template/Assets/Scripts/Editor/Build.cs), controlling the build from the editor
 - [XCodePostBuild.cs](template/Assets/Scripts/Editor/XCodePostBuild.cs), used for ios (**TODO**)
 - [UnityMessageManager.cs](template/Assets/Scripts/UnityMessageManager.cs), a script managing the messages between React Native and Unity
 - [Rotate.cs](template/Assets/Scripts/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](docs/android-player-settings.png)

#### ◼️ Additional changes for iOS Settings (**TODO**)

Under `Other Settings` make sure `Auto Graphics API` is checked.

![Player settings for iOS](docs/ios-player-settings.png)


### 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](docs/unity-build.png)

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:_
> ```bash
> # 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](#adding-unitymessagemanager-support)*

#### Example:

1. Send message from Unity
```C#
UnityMessageManager.Instance.SendMessageToRN("click");
```

2. Receive message in React Native
```javascript
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`

[**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>
    );
}
```

## 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`.

```C#
public class Rotate : MonoBehaviour {
    void handleMessage(string message) {
		Debug.Log("onMessage:" + message);
	}
}
```

2. Add Unity component to a GameObject.

3. Send message use javascript.

```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`](https://github.com/f111fei/react-native-unity-demo/blob/master/unity/Cube/Assets/Scripts/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#.

```javascript
void Awake()
{
    UnityMessageManager.Instance.OnMessage += toggleRotate;
}

void onDestroy()
{
    UnityMessageManager.Instance.OnMessage -= toggleRotate;
}

void toggleRotate(string message)
{
    Debug.Log("onMessage:" + message);
    canRotate = !canRotate;
}
```

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

```tsx
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](https://github.com/asmadsen/react-native-unity-view/tree/master/example) for a complete example

---
_Source: https://npm.io/package/@brice-gros/react-native-unity-view · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
