目的
自分の狙ったサービスを開発する上で、どうしてもReactとUnityを連携して作りたいと考え、ReactとUnityの連携部分を調査し実装しました。UnityをWebGLでビルドし、ReactからUnityの操作をできるようにすることを目的としています。
環境・バージョン
・開発PC: MacOS Catalina 10.15.7
・Unity: 2020.3.25f1
・React: 17.0.2
・react-unity-webgl:8.7.4
このプロジェクトではReactとUnityを連携するため、React用プロジェクトフォルダとUnity用プロジェクトフォルダを利用します。詳しくはGitHub リポジトリ をご確認ください。
React環境準備
まずはReactの環境準備です。今回のReactプロジェクトにはcreate-react-appを使いました。
create-react-appの準備はこのあたりを参考にされると良いかと思います。
https://qiita.com/ta1fukumoto/items/2b05ed74ba7332598d5f
node, npmのインストールができたらcreate-react-appを使って、Reactプロジェクトを作成します。下記の"react_unity"の部分は任意のフォルダ名にしてください。
$ npx create-react-app react_unity
ここまでできたら、一旦Reactを起動できるか確認してみます。プロジェクトフォルダに移動し、下記のコマンドでビルド、スタートします。
$ npm run build
$ npm start
するとブラウザが自動的に立ち上がり、React環境構築できたことを確認できます。

ここまで確認できたらUnityと連携するための準備します。"react-unity-webgl"を呼ばれるnpmパッケージをインストールします。リポジトリはこちら。 ドキュメントにも書いてある通り、今回はUnityの2020向けなので下記のようにインストールしました。
$ cd ./react_unity
$ npm install react-unity-webgl@8.x # For Unity 2020 and 2021 (Current)
Unityシーンの作成・WebGL用ビルド
次にUnityプロジェクトを用意しましょう。
Unityで適当なシーンを作り、操作対象とするオブジェクト(下記の例ではsphereとしました。)

オブジェクトを生成した上で、MonoBehaviorを継承したスクリプトをアタッチ。下記のようにコードを記述します。
この
- public void MoveRight(int position)
- public void MoveLeft(int position)
- public void MoveUp(int position)
- public void MoveDown(int position)
がReact側から呼ばれる想定のメソッドです。

using System.Collections.Generic;
using UnityEngine;
public class BallController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void MoveRight(int position)
{
this.gameObject.transform.position += new Vector3(position, 0, 0);
}
public void MoveLeft(int position)
{
this.gameObject.transform.position += new Vector3(-position, 0, 0);
}
public void MoveUp(int position)
{
this.gameObject.transform.position += new Vector3(0, position, 0);
}
public void MoveDown(int position)
{
this.gameObject.transform.positio n += new Vector3(0, -position, 0);
}
}
これでWebGLビルドをすればUnity側の準備はOKです。

Unityのビルド済ファイルをReactにインポート
こうしてビルドしたUnity側のファイルを先ほど作成したreact側プロジェクトののpublic/以下に移します。
コピー元

これでReact側でUnityを呼び出すための準備ができました。
ReactからのUnity呼び出し実装
最後にReactからUnityのシーンを呼び出す実装をします。この実装もこちらのReadMeを参考に実装しています。更新するのはReactプロジェクトの中のsrc/App.jsです。
先ほどインポートしたUnity関連ファイルを使って、Unityのクラス、シーンオブジェクトにアクセスできるように、UnityContextを作成します。このUnityContextを使って、Unityシーン内のオブジェクト、関数などにアクセスすることが可能です。
下記の例では球体を右、左に動かすボタンを用意しました。
import './App.css';
import React from "react";
import Unity, { UnityContext } from "react-unity-webgl";
const unityContext = new UnityContext({
loaderUrl: "UnityBuild/webgl_app.loader.js",
dataUrl: "UnityBuild/webgl_app.data",
frameworkUrl: "UnityBuild/webgl_app.framework.js",
codeUrl: "UnityBuild/webgl_app.wasm",
});
function App() {
function moveRight() {
unityContext.send("Sphere", "MoveRight", 10);
}
function moveLeft() {
unityContext.send("Sphere", "MoveLeft", 10);
}
return (
<div>
<button onClick={moveRight}>MoveRight</button>
<button onClick={moveLeft}>MoveLeft</button>
<Unity unityContext={unityContext}
style={{
height: "100%",
width: 400,
border: "2px solid black",
background: "grey",
}}/>
</div>
);
}
export default App;
※著者の場合、最初はシーンのサイズを指定しませんでしたが、その場合サイズがかなり巨大になってしまって非常に重くなってしまったのでサイズを指定するようにしました。
Reactのビルドと実行
App.jsを更新したら、再度Reactプログラムをビルドし、スタートします。
$ npm run build
$ npm start
これで下記のようにUnityシーンを操作できるReactプログラムを動かすことができます。

いかがでしょうか。ここまででReactからUnityの呼び出しを実装することができました。よろしければその2のUnity→React呼び出しもご参考ください。