【UnityRenderStreaming×ARFoundation】スマホ向けのビデオストリーミング & カメラ制御してみた

# はじめに
こちらはIwaken Lab. 主催のXR好き開発合宿ブログリレーの14日目の記事になります。この記事では、開発合宿中に触っていた技術について書かせてもらいます。

https://iwakenlab.jp/

また、XR好き開発合宿では、たくさんの方々から温かいお言葉や支援をしていただきました。この場をお借りして感謝申し上げます。本当にありがとうございました。

# この記事の概要
UnityRenderStreamingの機能を使って、処理の重たい描写をグラボがついてるPCに任せて、その映像をスマホで見れるようにし、ARFoundationを利用することで、PC上で動作するカメラの位置情報と回転情報をスマホで制御できるようにしました。

![システム図 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/fbc46cd6-aac2-a3d9-7b0d-45e16d7c220e.jpeg)


スマホの傾きや位置がUnityのシーン内のカメラに連動しているため、動画のように、様々な角度や位置からUnityのシーン内を見ることができます。

<iframe width="560" height="315" src="https://www.youtube.com/embed/0xzvvY5Tsbc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

この記事ではスマホのブラウザでビデオストリーミングするのではなく、**スマホのネイティブアプリとしてビデオストリーミング**を行なっており、また、**ARFoundationの平面検知やフェイストラッキングの機能を使ってARをするわけではない**と言うことにご留意ください。

# 動作環境
- UnityHub version 3.2.0[^1]
- Unity version 2020.3.8f1
- UnityRenderStreaming version 3.1.0-exp.3
- windows 11 pro / gigabyte x299 aorus gaming 7 pro(NVIDIA GeForce RTX 3070)
- Xperia 5 Ⅱ SOG02SLA

# UnityRenderStreamingについて
UnityRenderStreamingとは、Unity上でレンダリングされた映像をブラウザやスマホで見れるようにしたり、ブラウザからの入力をUnityに反映させたりできる機能のことです。

この機能を用いることで高品質なグラフィックスを、レンダリングが苦手なデバイスでもみることができたり、Unityでの操作をブラウザでもできるようになります。
詳しくはこちらをご覧ください。

https://blog.unity.com/ja/technology/stream-high-quality-real-time-graphics-through-your-browser-with-our-new-webrtc


https://docs.unity3d.com/ja/Packages/com.unity.renderstreaming@3.1/manual/index.html


# ARFoundationのサンプルのダウンロードとプロジェクトの開始
こちらのサイトから`arfoundation-samples-4.1`をZip形式でダウンロードして、展開した後、そのファイルをUnityのバージョンが`2020.3`以降のもので開きます。

https://github.com/Unity-Technologies/arfoundation-samples/tree/4.1


# UnityRenderStreamingとSamplesのインポート
公式サイトを参考にして行っていきます。

https://docs.unity3d.com/ja/Packages/com.unity.renderstreaming@3.1/manual/installation.html

Unityのパッケージマネージャーを開いて、左上の+ボタンを押し、`Add package from git URL...`を選択します。そして、出てきたボックスに`com.unity.renderstreaming@3.1.0-exp.3`と入力して、Addします。
![スクリーンショット 2022-10-06 103530.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/7f0f7cc5-5574-cb31-1945-913824402e92.png)

UnityRenderStreamingがインポートできたら、UnityRenderStreamingのパッケージに含まれている`Samples`もインポートしておきます。
![スクリーンショット 2022-10-06 105414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/32d2ec73-e30f-cc0b-f2c7-9b2912442aa0.png)

# ユニティちゃんのダウンロードとインポート
こちらのサイトから`ユニティちゃんライブステージ！ -Candy Rock Star-`をダウンロードして、展開したファイルをUnityのAssetsにドラッグ＆ドロップします。

https://unity-chan.com/download/index.php

Unityに`unitychan-crs-master`がインポート出来たら、コンソールを確認します。もし、コンソールにこのようなエラーがでたら、該当箇所をコメントアウトします。
![スクリーンショット 2022-10-13 151124.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/d441a512-06f8-6fd7-7af2-17b7eeb1fa10.png)

```:Camera-DepthTexture
v2f vert( appdata_full v ) {
    v2f o;
    // TreeVertBark(v); ここをコメントアウト
	
	o.pos = UnityObjectToClipPos( v.vertex );
    UNITY_TRANSFER_DEPTH(o.depth);
    return o;
}
.
.
.
v2f vert( appdata_full v ) {
    v2f o;
    // TreeVertLeaf(v); ここをコメントアウト
	
	o.pos = UnityObjectToClipPos( v.vertex );
	o.uv = v.texcoord.xy;
    UNITY_TRANSFER_DEPTH(o.depth);
    return o;
}
```

# Broadcastシーンの編集
Assets/Samples/Unity Render Streaming/3.1.0-exp.3/Exampleの中にある、Broadcastシーンを開き、`Plane`と`Sphere`を削除します。削除した後、Assets/unitychan-crs-master/unitychan-crs-master/Assets/Scenesの中にあるMainを選択して、右クリックで`Open Scene Additive`します。
![スクリーンショット 2022-10-13 152233.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/5341a5ed-4c1c-b3e7-a4f7-7f35715f61fd.png)

シーンを追加したら、`Stage Director`と`App Config`を複製して、Broadcastシーンに追加します。
![ezgif-5-2fe3cc0781.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/23ef3476-2a04-f630-3605-86ac0cba1702.gif)

それが終わったら、Mainの横にある三点リーダーを選択して、`Remove Scene`をします。
![スクリーンショット 2022-10-13 153842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/cb3a187a-1151-9fae-33e2-a39987dec5c3.png)

# Buildの設定からBuildまで
スイッチプラットフォームでAndroidを選択して、Assets/Samples/Unity Render Streaming/3.1.0-exp.3/Exampleの中にあるシーンを`Scenes In Build`に追加します。この際、`Menu`シーンを一番上にする必要があります。
![スクリーンショット 2022-10-13 162948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/95b918a4-7206-d3f4-12cb-2263634de861.png)

次はBuild設定をします。Project Settingsの`Player`の中にある`Other Settings`で次のように設定を変えます。
![スクリーンショット 2022-10-13 164709.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/ef64a5f8-7ff4-a4d5-c4b8-2c5ae6132ffb.png)

そして、`XR Plug-in Management`の中にあるAndroidタブで`ARCore`にチェックをいれます。
![スクリーンショット 2022-10-13 165115.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/5cfa3e46-9820-8074-e6a2-84df8311fe9e.png)
これらすべてが終わったら、Buildをします。

# ウェブアプリケーションのダウンロードと起動
Unityのメニューで`Edit`を選択し、その中にある`Render Streaming`の`Download web app`を選択します。すると、アプリケーションの保存先を聞かれるので、適当な場所を指定します。
今回は`Server`というフォルダをつくり、そのなかにアプリケーションを保存しました。
![スクリーンショット 2022-10-06 133032.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/f44baa6c-2198-0697-01b8-14b4ab2ad683.png)

次に、保存したディレクトリに移動して、`.\webserver.exe -w`を実行します。
![スクリーンショット 2022-10-13 135110-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/4acce9ba-1c22-f7fe-0b09-3f2a34b0bb6a.png)

なお、Macの場合は、`chmod a+x ./webserver_mac`でパーミッションを変えてから`./webserver_mac -w`を実行する必要があります。

# アプリとUnityでの操作
BuildしたアプリをAndroidにインストールして、アプリを起動します。アプリを起動すると、次のようになっているので、Addressの`localhost`を選択して、上の画像の、黄色い線で示したアドレスを入力します。今回の場合は`192.168.10.8`です。

<img width="30%" alt="XRecorder_13102022_173022.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/e1bc63c7-991f-aa43-9f96-3f3e0666d4ca.jpeg">

次に、Unityで`Broadcast`シーンを開き、シーンをPlayします。

そして最後に、アプリで`AR`を選択し、次のような画像の状態で、`Start`を押すと、`Broadcast`シーンのカメラの映像がスマホに表示されます。

<img width="30%" alt="XRecorder_13102022_173233.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/dd50dab5-accc-26d8-b8ea-3f4e24cbf678.jpeg">

スマホを傾けると、Unity内のカメラも傾いているのが分かります。
![ezgif-4-5bd0815ff9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/1ad3e116-daeb-7791-0447-ade785facc08.gif)

# まとめ
今回はUnityRenderStreamingとARFoundationの機能を使って、スマホでビデオストリーミングとカメラ制御をする方法を紹介させてもらいました。ほかにもUnityRenderStreamingを使うと、ブラウザとUnity上でマルチプレイをすることができたり、Zoomのような双方向通信を行うこともできます。
詳しく知りたい方はこちらのサンプルが参考になると思います。

https://docs.unity3d.com/ja/Packages/com.unity.renderstreaming@3.1/manual/samples.html

また、今回は紹介できませんでしたが、**ARFoundationの平面検知などの機能もUnityRenderStreamingと併用して使うこともできる**ので更なるアレンジをすることもできます。

皆さんも是非、UnityRenderStreamingを試してみて下さい！

最後まで閲覧していただきありがとうございました。

[^1]:自分の環境では、UnityHub version 3.2.0の時は、ちゃんとPCとスマホの通信ができていたが、version 3.3.0にしてからうまくいかなくなったので、念の為、記述しました。