UnityをWebGLビルド・Reactと連携してWebアプリを構築してみる その１



## 目的

自分の狙ったサービスを開発する上で、どうしても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プロジェクトのソースコード(github)](https://github.com/kchan0514/react-unity-bridge-example)
- [Unityプロジェクトのソースコード(github)](https://github.com/kchan0514/react-unity-bridge-example-unityprj)


## 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環境構築できたことを確認できます。

<img width="600" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/2e6bf6a7-b74c-b505-c721-d4c1ef17587a.png">

ここまで確認できたらUnityと連携するための準備します。"react-unity-webgl"を呼ばれるnpmパッケージをインストールします。リポジトリは[こちら。](https://github.com/jeffreylanters/react-unity-webgl) ドキュメントにも書いてある通り、今回はUnityの2020向けなので下記のようにインストールしました。

```
$ cd ./react_unity
$ npm install react-unity-webgl@8.x  # For Unity 2020 and 2021 (Current)
```

## Unityシーンの作成・WebGL用ビルド

次にUnityプロジェクトを用意しましょう。
Unityで適当なシーンを作り、操作対象とするオブジェクト（下記の例ではsphereとしました。)

<img width="600" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/1d76c03f-85c4-a382-939f-2735cf6380bf.png">


オブジェクトを生成した上で、MonoBehaviorを継承したスクリプトをアタッチ。下記のようにコードを記述します。
この

- public void MoveRight(int position)
- public void MoveLeft(int position)
- public void MoveUp(int position)
- public void MoveDown(int position)

がReact側から呼ばれる想定のメソッドです。

<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/43b6cb1e-92a0-8ef7-b21f-23303a88fda0.png">


```
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です。

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/ec4809e5-e7f6-e4c4-667c-c67233f4efa8.png">


## Unityのビルド済ファイルをReactにインポート

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


コピー元

<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/219dc2ea-98d3-687c-4720-cf8f3fa79fd8.png">



コピー先
![スクリーンショット 2022-02-06 14.46.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/0edf53fb-f5ad-5848-e9d0-76c2534d8a93.png)


これでReact側でUnityを呼び出すための準備ができました。

## ReactからのUnity呼び出し実装

最後にReactからUnityのシーンを呼び出す実装をします。この実装も[こちら](https://github.com/jeffreylanters/react-unity-webgl)の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プログラムを動かすことができます。

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111483/f4de2c35-bf6e-d945-f916-f2c14eb826f0.png">


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

https://qiita.com/GIZAGIZAHEART/items/da9c5d949cbf08e2c8c9