【Unity】UnityRenderStreaming スマホARと連動させてみた編【CloudRendering】


# TL;DR
- ARカメラを入力としてクラウドレンダリング上のコンテンツを操作するサンプルの動かし方の解説です

https://twitter.com/8bitdots/status/1605452340592406529

# 前章
まずはUnityRenderStreaming 導入を行う必要があるので前回の記事を必ずご一読ください。

https://qiita.com/Cova8bitdot/private/9bc3b1b3dc394d81d665

また、今回はGCPを利用するため、環境によってはインスタンス費用が発生するのでご注意ください。

# AR サンプルを動かす
## 前提

前回はローカル環境で動かしましたが、スマホを入力とするので当然ですがローカル環境では通信ができません。
そこで、通信のリレーサーバーを用意して中継させることでPCとスマホを繋げることができます。

また、同一ネットワークである制約も無くせるため、リレーサーバーを立てるところが大きく違います。

### リレーサーバー

今回はRemotePCとスマホでP2Pで通信を行うのですが、環境によってはNAT越えができない場合があります。
（マンション等でSplatoon で通信エラーになる等）

そのNAT超えが可能かどうかを判定するのがSTUNサーバーであり、NAT超えが必要な場合に、通信の中継地点になってくれるのがTURNサーバーです。

TURN/STUNサーバーの解説はこちらの記事がめちゃくちゃ初心者にはオススメなので、ぜひご一読ください。

https://qiita.com/okyk/items/a405f827e23cb9ef3bde

### coturn
coturn はOSSで開発されているTURN/STUN がオールインワンで提供されているパッケージです。

https://github.com/coturn/coturn

今回TURNサーバー実装ではcoturnを利用します。


## Android アプリをビルドする
### step.1 Android ビルドモジュールを入れておく
当たり前ですが、Android ビルドモジュールがないとAndroid ビルドは出来ません。
導入してない場合はUnityHub から追加でモジュールを入れましょう

### step.2 switch platform
こちらもそうですが、Android にプラットフォームを変えましょう。
`cmd + shift + b` (windows は `ctrl + shift + b`) でBuildSettings ウィンドウを立ち上げて
プラットフォームをAndroid に設定して switch platform しておきましょう。

### step.3 AR Foundation を導入する
PackageManagerを開き、上部のPackages を `UnityRegistry` に変更します。

![スクリーンショット 2022-12-20 17.38.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/ac00b25f-13c5-6754-b63e-92a46b45c416.png)

その後、表示されるリストからARを選択して install ボタンを押せばOKです
![スクリーンショット 2022-12-20 17.38.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/3fa2a5a5-b7c4-d203-268b-c174a702e47c.png)

### step.4 XRモジュールの有効化

メニューバーから `Edit` → `ProjectSettings` と選び、ウィンドウを立ち上げて
`XR Plug-in Managemanet` の項目を選択します。

その後Android アイコンを選択してTabを切り替えて、ARCore にチェックを入れます。
![スクリーンショット 2022-12-20 17.40.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/0597781e-293e-352e-a1c5-e7a781761c06.png)

### step.5 Sceneの登録
`cmd + shift + b` (windows は `ctrl + shift + b`) でBuildSettings ウィンドウを立ち上げて
BuildSettings のScene に `Menu` と `ARFoundation` を登録します。

![スクリーンショット 2022-12-20 17.35.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/d2083dba-70de-67cd-0a64-5d135f348477.png)

### step.6 ビルド
step5 に続いてBuildSettings ウィンドウ下部の `Build` ボタンを押します。
そしてAPKファイルの保存先を選択したら、無事ビルドが終わるように祈りましょう。

#### com.android.ide.common.signing.KeytoolException

上記の例外が出てビルドが止まる場合、Home 直下にある .android フォルダ以下にあるdebug.keystore が悪さをしている可能性があります。
この場合はdebug.keystoreを削除することで回避可能です。

### step.7 apk ファイルをAndroid端末に突っ込む
adb 経由でもいいし、GoogleDrive 経由なりでapkファイルを導入して、無事起動すれば準備OKです

## P2Pのリレーサーバーを立ち上げる
リレーサーバーは大きく分けて3つの工程に分かれます。
1. GoogleComputeEngine のインスタンス立ち上げ
2. coturn の設定
3. Unity公式のwebserverアプリの設定

### step.1 GCE インスタンスの作成
#### ComputeEngine のページへ移動
![スクリーンショット 2022-12-21 11.35.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/8255be89-b1be-3c81-6ee4-ca6a7f8d1075.png)


もしProjectがなくてこのような画面の場合はProjectを作成してください
![スクリーンショット 2022-12-21 11.36.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/babad2de-3223-d3f1-edc8-a4c7c6bd3516.png)

#### VMインスタンスを作るボタンをポチる
![スクリーンショット 2022-12-21 11.36.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/fb0eaec0-1966-9c25-fb94-627b13f59264.png)

#### 名前、リージョン、ゾーンを設定
もし費用的に余力があるならリージョンはasia-northeast1/asia-northeast2, ゾーンは asia-northeast系のいずれか　で設定すると通信が早くてオススメです。

![スクリーンショット 2022-12-21 11.36.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/b34dd29d-ad0f-050a-0530-2caecc340c16.png)

#### OSイメージを変更する
1. 変更ボタンを押す
![スクリーンショット 2022-12-21 11.36.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/68c20d3f-32d7-6ffc-350d-8963e43d8463.png)

2. OS を`Ubuntu` バージョンは `LTS Minimal` の新しめのやつにします
![スクリーンショット 2022-12-21 11.38.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/f135c0c4-ecb5-75d3-c281-bd657c708b65.png)

※公式では `ubuntu-minimal-1604-xenial-v20190628` とありますが、選択肢に出てこなかったので上記で代用します。

#### Firewall でHTTP/HTTPSトラフィックを許可にチェックを入れる
![スクリーンショット 2022-12-21 11.38.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/815529bc-677f-6303-84e1-2d1b4ee40300.png)

#### インスタンスを実際に作る

### step.2 coturnの導入
#### ssh でインスタンスに接続する
無事にインスタンスを作成できたら、今度はコンソール上で作業します。
ComputeEngine Top画面から生成したインスタンスの名前を選択すると、詳細ページへ飛ぶことができます。
詳細のTopページのsshボタン右の▼アイコンを選ぶとリストが表示されるので `gcloudコマンドを表示` を選択します。
![スクリーンショット 2022-12-21 11.52.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/b0bc9822-3c02-8f3e-4b43-77bdd56646b9.png)

そうするとgcloudを用いてssh接続するコマンドが表示されるのでメモしておきましょう。
```
gcloud compute ssh --zone "asia-northeastのどこか" "VMインスタンス名"  --project "ここにプロジェクト名がはるはず"
```

GCloud CLIをインストールしてない場合はここで入れましょう。

https://cloud.google.com/sdk/docs/install?hl=ja

無事CLIツールをインストールしたら先ほどのコマンドをターミナル(コマンドプロンプト上）で実行してください。

```
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.15.0-1025-gcp x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

0 updates can be applied immediately.
```
このような形のメッセージが出ていればおおむね大丈夫です。

ちなみに、GCPのブラウザコンソールから行おうとするとさまざまなエラーに遭遇してうまくいかなかったので、必ずssh接続して次の作業に進んでください。

#### coturnを入れる

公式マニュアルに従ってcoturnを入れていきます。
https://docs.unity.cn/Packages/com.unity.renderstreaming@2.0/manual/jp/turnserver.html#coturn-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

```
$ sudo apt install coturn
```
でcoturnを入れます。

続いてvi/vim が無いので追加します。
```
sudo apt install vim
```

そして、coturnの起動設定ファイルを変更します。
```
sudo vim /etc/default/coturn
```

で設定ファイルを開いて `TURNSERVER_ENABLED=1` の行のコメントアウトを解除します。

次にcoturnの設定ファイルを編集します。
```shell
sudo vim /etc/turnserver.conf
```

```shell
# ポート設定する(公式には記載ないので注意)
listening-port=3478

# 外部のピアに教える TURN サーバーが待ち構えるIPアドレス（VMインスタンスの外部IPアドレスを入力）
external-ip=xx.xx.xx.xx

# 認証を有効化する(コメントアウトを解除する)
lt-cred-mech

# ユーザ名とパスワードを指定
user=username:password

# レルムの設定
realm=yourcompany.com

# ログファイルの設定
log-file=/var/tmp/turn.log
```

なお、設定した項目を確認する場合は以下のコマンドを実行するのがオススメです
```shell
$ cat /etc/turnserver.conf | grep -v -e '^\s*#' -e '^\s*$'
```

設定が完了したらcoturnを再起動します
```
sudo systemctl restart coturn
```

#### 疎通チェック

https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/

上記のサイトに飛んで、最後に作成したcoturnが動いてくれるかをチェックします。

まずはサーバー設定で、xx.xx.xx.xxの部分とUsername/Password の部分を書き換えてAddServer ボタンを押します。
![スクリーンショット 2022-12-21 12.09.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/d4c399c4-a4b6-ac07-e3d7-924f430588dd.png)

続いて下の画面にある `Gather candidates` ボタンを押します。

![スクリーンショット 2022-12-21 12.10.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/cfda33a2-d6f4-0c53-af7d-926b6fbeec1c.png)

結果、下のような形でズラッと出てきてDoneが最後にあればOKです。
![スクリーンショット 2022-12-21 12.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/029ba40a-9231-25ce-cf31-5606c4bfbb70.png)

### step.3 WebServer アプリのビルド
最後にSignaling サーバーの役目を行うソフトウェアを導入します。
VMインスタンスにssh中だと思いますので、まずは必要なツール群を入れます。

```shell
# Git 導入
sudo apt install git
# 多分npmも無いので 導入
sudo apt install npm
```

その後、webserver.exe の代わりとなるものを導入するため、公式からリポジトリをcloneします。
```
git clone https://github.com/Unity-Technologies/UnityRenderStreaming
```

clone が終わったら以下のコマンドを順番に叩いてweb server を起動します。
```
cd UnityRenderStreaming/WebApp/
npm install
npm run build
npm run start
```

これでようやくサーバー側の準備は完了です。

詳しい手続きは以下の公式のページをご確認ください。

https://docs.unity.cn/Packages/com.unity.renderstreaming@3.1/manual/customize-webapp.html

## 動作チェック

ようやくお膳立てが終わったので、実機を用いてチェックします。

### step1. UnityEditor でMenu.scene を再生して準備
![スクリーンショット 2022-12-21 15.26.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/f7c5fe5a-1f9b-ee95-4530-ac1cd9c599dc.png)

1. 画面右下のType を `Http` に、Address 部分に　`外部IPアドレス` を入力します。
1. 画面上部にある `Broadcast` ボタンを押してScene遷移します

### step2. スマホ側でも準備

1. step1と同じく `Http` に、Address 部分に　`外部IPアドレス` を入力します。
1. step1とは異なり、スマホ側では `AR` ボタンを押してScene 遷移します。
1. 下記スクショの画面に遷移するのでStartボタンを押してしばらく待ちます<br>もし接続に問題がなければUnityEditorのGameViewの画面がスマホ側に映ります。<br>![Screenshot_20221221-153010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/4d37c6e9-c7da-2651-2070-cc01d0402b59.png)

### 実機映像

https://twitter.com/8bitdots/status/1605452340592406529


# ハマったところ
## 概念理解
ARとPCを連携する上で、web server application をどこで動かすのか最初イマイチわかりませんでした。
exeをGCEで動かすの？という固定観念に囚われてましたが、普通にgit clone でリポジトリ引っ張ってきてnpm でビルドすればいいとわかって一気に進みました。

## coturn が動かない
最初GCPのブラウザからコンソールを立ち上げて設定をやっていました。
しかし
```shell
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
```
とエラーがでてきて systemctl をたたけませんでした。

こちらは素直にssh接続にすれば解決できるので、ブラウザのコンソールでは作業しないようにしましょう

## npm が動かない
apt-getでnpmを入れたときに node.js のバージョンが古すぎてnpmとnode.jsのバージョンが一致しないエラーに遭遇しました。
`npm install -g n` をやってもsyntaxエラーでダメでした。

こちらは以下の記事を参考に node.js を入れ直すことで解決できました。

https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04-ja

## CloudRenderingが動かない
- UnityEditorを再生中やスマホに入れたアプリの設定で `websocket` になっている
- GCE上でwebserver application を動かしてない
- coturnの設定がおかしい
- 外部IPではなく内部IPを入力してしまっている

このあたりが見直すべきところだと思います。


# 最後に
Experimental 版なので動作が安定しない可能性がありますが、少なくとも2〜3日ほどかければ動かすことができました。
今回の手順をもとにやれば数時間で動作チェック出来ると思いますので、クラウドレンダリングに興味がある方はやってみても面白いかと思います。


# 参考

https://qiita.com/okyk/items/a405f827e23cb9ef3bde

https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04-ja