AR FoundationをEditorでも動かす その2

【unityプロ技】 Advent Calendar 2019 - Qiita 6日目の記事です。*1

img

Imgur

はじめに - ARFoundationとは

スマートフォンでのAR楽しいですね。それぞれiOSはARKit、AndroidではARCoreというAR用開発キットが公開されています。Unity用SDKもそれぞれUnity-ARKit-Plugin,Google ARCore SDK for Unityと開発がされてきました。今まではそれぞれのSDKをインストールして頑張ってきたのですが、ARCore, ARKit, HoloLens, Magic LeapSDKをラップして、同じAPIでアクセスできるようにする、ARFoundationが発表されました。

ARFoundationの導入は、安定のテラシュールブログさんを御覧ください。 tsubakit1.hateblo.jp

何を作った?

ARFoundationはUnity-ARKit-PluginのときよりもAPIがシンプルでわかりやすいのですが。以前のこちらの日記でも簡単に書いたように、 Editorで動かない。毎回実機ビルドが必要という問題がありました。Unity-ARKit-Pluginのときはできていたんです…。つい昨日、公式からアナウンスがあり、2020年はじめにリモートでつなげてEditorでも動作できる機能をリリース予定です。とはいえ、今すぐ仕事で使うために、自分で使う一部機能だけでもEditorで動かせると便利だと思ったので、ARKit3の新機能だけでもEditorで動作するものを作りました。*2

asus4.hatenablog.com

github.com

今回エディタ側で対応した機能は、 - 人間の体部分を検出 - Face - 座標検出 - Mesh検出 - ブレンドシェイプ推定 です。 以下は作例です。Editorで動作することで、デプスを送りながらVisual Effect Graphでノードのパラメータをいじるなどといったこともできるようになっています。

使い方

簡単に使い方を説明します。

1. NDIのインストール

iPhoneのカメラで移している映像をUnityに送るためにNDIを使っています。iPhoneで使うためには、NDIを https://ndi.tv/sdk/ からインストールする必要があります。メールアドレスを登録してしばらくするとSDKのダウンロード先URLが送られてきます。

2. iPhoneに送信用アプリをインストール

GitHubからUnityプロジェクトをダウンロードして、 iPhone用にビルド。Xcodeから対応端末 (iPhoneX以降〜)へインストールします。

3. maciPhoneをUSBでつなげる

高速のWi-Fiの場合は良いですが、私のオフィスのネットワーク環境ではiPhonemaciPhone USBネットワークで接続したほうが遅延が少なく動作しました。

Imgur

4. 再生する

iPhoneの送信側と対応するシーンをUnityEditorでも開きます。
iPhoneを再生すると、同じネットワークにNDIが飛んでいる場合、NDIの名前が表示させるので、NDI ReceiverコンポーネントのSource Nameにセットしてください。 Imgur

Unity Editorを再生開始するとiPhoneと同じ画面が表示されると思います。

ARFoundationを中身を見てみよう

この開発をするために、ARFoundationの中身を詳しく知る必要があったので、紹介します。

最新のロードマップ、Unite Copenhagen 2019でのスライドにあるように、AR Foundationを抽象化されたAPIの一個深いレイヤーにはSubsystemというものがあります。平面を検出する機能を例に取ると、

f:id:asus4:20191207001738p:plain
こんな感じ

それぞれのプラットフォームフォームがSubsustemを持っています。対応していないplatformではSubsystemがnullを返します。Manager側が何も動作しないので、シーン中にManagerコンポーネントが配置されていても問題ありません。そして、UnityEditorで実行するときは、Subsystemは存在しないので、エラーは返さないものの、動作しません。

そこでUnity Editor用のSubsystemを追加して、ARFoundationとは別の経路でiPhone実機から同等のデータを送信。このEditor用SubsystemをAR FoundationのハイレベルAPIに同じデータを転送。

f:id:asus4:20191207003135p:plain
エディタのSubsystemを追加

一番上のレイヤーから見ると、動作は何も変わっていないので同じコードで動作する気がします。

Subsystemの作り方

ここまでがわかったいくつかのSubsystemを自分で作ってみました。GitHubのリンクはこちらです

セッション管理をしているXRSesseionSubsystemをEditorで対応する例です。

// 仮想コード
namespace ARKitStream.Internal
{
    // PreserveはCode strippingでコードが消されないようにしてるっぽい。
    [Preserve]
    public class ARKitSessionRemoteSubsystem : XRSessionSubsystem
    {
        protected override Provider CreateProvider() => new ARKitRemoteProvider();

        // サブシステムの初期化時にUnityEngineから実行される
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
        static void RegisterDescriptor()
        {
            // UnityEditorのときだけサブシステムを作る
#if UNITY_EDITOR
            const string id = "ARKit-Remote-Session";
            XRSessionSubsystemDescriptor.RegisterDescriptor(new XRSessionSubsystemDescriptor.Cinfo
            {
                id = id,
                subsystemImplementationType = typeof(ARKitSessionRemoteSubsystem),
                supportsInstall = false,
                supportsMatchFrameRate = false
            });
#endif // UNITY_EDITOR
        }
        
        // サブシステム本体
        // 各サブシステムにはProviderと呼ばれる本体のクラスがいる。
        class ARKitRemoteProvider : Provider
        {
            //
        }
    }
}

かなりシンプルに書いていますが、このようにRuntimeInitializeOnLoadMethodアトリビュートでSubsystemを管理しているようです。RuntimeInitializeOnLoadMethodは今回始めて使いましたが、UnityEngineネームスペースにあるので、ARFoundation以外にもSubsystemを使っているライブラリがあるのかもしれません。

まとめ

  • AR Foundationを使うと簡単にマルチプラットフォームなARアプリを作成できます。
  • Editorでも一部の機能を動作させることができた。
  • Unity開発チームが来年はじめに、Editorで動くやつを公開してくれる予定。

以上です。

*1:ML-Agents付属のBarracudaのドキュメントが少ないので、詳細を書こうとしたのですが、玉砕したので内容を変更しています

*2:また別の選択肢とて1→10さんが開発しているZIG SIM PROもいいかもしれません。NDIとOSCで、ARKit3のいくつかの機能を送信できます。有料ですが、時間節約できるので一瞬で元取れます。