GoogleのARハッカソンでBest賞をもらいました

GoogleのGeospatial APIを使ったARハッカソンGoogle’s Immersive Geospatial Challengeで、友人の音楽家 Twothと一緒に制作したARアプリが、AR | Best of Entertainment & Events というARのエンタメ部門で1位の賞をもらいました。

GoogleのDeveloperブログに取り上げてもらいました。一番目のコンテンツ、World Ensembleが私達のプロジェクトです。
developers.googleblog.com

説明動画も作りました。(Adobe全部アンイストールしてたので、初めてDaVinci Resolveで編集しました。)
www.youtube.com

他の受賞プロジェクトも面白いアイディアが沢山ありました↓
Google’s Immersive Geospatial Challenge: Go beyond the map in Google’s Immersive Geospatial Challenge - Devpost

Behind the Scenes

普段のフリーランスとしての受託プロジェクトでは中々制作過程を見せることは出来ないのですが、このプロジェクトではソースコードを公開することが参加ルールの一つでした。
折角なので少し制作の裏側を残します。

またクリエイティブ・コモンズ ライセンスでGitHubにプロジェクト一式を公開しています。(音も一緒にCCライセンス公開に同意してくれてありがとうございました。)

github.com

Visual Effects

AnroidでARアプリを作るとき、最新ARCore NativeではついにVulkan対応が入りましたが、Unityから使う際のARFoundaitonは未だにOpenGLESでの実行になります。そのためにUnityの新しいVFX機能であるVFX Graphを使えませんでした。VFX GraphはOpenGLESに対応していないのです。ARアプリでリッチなVFXを作りたいときの一つの障壁とも言えます。
そのため、今回はシンプルなShiriken Partilceを基本に構成しています。その代わり、パーティクル一粒一粒のシェーダーをすべてカスタムすることにしました。
シンプルなShuriken Particleを使っても、一つ一つのパーティクルの見た目にこだわれば結構行ける感触がありました↓

シェーダーは基本的にはShaderGraphで作りました。

今回はAR空間で映える見た目と言うことで、Scene Color Nodeという、現在カメラにレンダリングされているテクスチャにアクセスするノードを多用し、ガラスっぽかったり(光学的な計算はまったく間違っています)現実空間の建物をグリッジ風にしたりしてみました。

Bubble shader graph

モバイル向けに重いShaderは、以下のように、ShaderGarphの中でHLSLのコードを叩くという方法を使ってます。
URPが主流になってからというもの、いろいろな種類のPassやSingle-pass instanced renderingの対応などが面倒くさくなって、生のShaderを書かずに、こんな感じのハイブリッドな構成が多くなりました。複雑なロジックはHLSLで書きつつ、複数の実行環境への対応をShaderGraphがよしなに追記してくれるので結構気に入っています。

Cecium TileSet Shader optimization

3Dサウンド

音はTowthに作ってもらった音をARの3D空間上に配置しています。内部的に16 stepシーケンサーを動かして、3D上でタイミングが来ると音がなるようになっています。
実験的な機能として、屋外のでかいARコンテンツなので音速が考慮に入れて、聴取者までの距離によって音速の遅延をいれるなど、色々遊びました。
この時に使いにくかった、SFX Reverbの使い方をZennに記事を残しています。

仮想空撮 → 現実空間ARへのトランジション

Aerial to AR

今回、実験したものの一つに、Cesiumで読み込んだ3D tilesから AR画面へのトランジションでした。空をタップすると、上空100mへジャンプして、自分のAR画面へ戻って来ます。これは試しに、GeoSpatialPoseのGPS座標とEast-Up-North rotation 、 を元に、Cesium上の3Dモデルに重ね合わせてみると思ったより精度が高く、面白い演出になりそうだったので、急遽取り入れた機能でした。
コア部分は以下のような3行で実現可能です。

var geoPose = _earthManager.CameraGeospatialPose;
_globeAnchor.longitudeLatitudeHeight = new(geoPose.Longitude, geoPose.Latitude, geoPose.Altitude);
_globeAnchor.rotationEastUpNorth = geoPose.EunRotation * _rotationOffset;

AR シミュレーション in UnityEditor

今回、11月20日の締切に対して、空のUnityプロジェクト作って手を付け始めたのがは11月7日、2週間前でした。仕事なら炎上どころではないスケジュールです。…し、別のAR仕事が忙しかったので…。

いくつかのVPS (Visual Positioning System) ARアプリを開発をして来ましたが、必ず出くわす問題が、Unity Editorでは動くのに実機で街に出て動かすと全然動かない…。というやつです。

もちろん普通のアプリでも起きますが、VPSは、GPSの精度、ネットワーク速度、遠くのメッシュは読み込まれてない…。などなど現実の空間でしか起こらない環境要因が盛り沢山です。

そんななか、今回の高速開発を支えたのが、去年から空き時間にちまちまR&Dしていた、ARFoundation Replayです。これは4年前に開発していたARKitStreamerの後継ライブラリです。

以前のものと同じく、Unity Editor上でAR FoundationのSubsystemを動かしますが、以前はPCとWi-FiもしくはUSBで接続したiPhoneから送られてくるリアルタイムのデータしか対応していなかったものが、今回は、VPS対応のために、出先でiPhoneアプリ上でARを録画、Photoに保存して、家に戻って、PCで動画ファイルをUnityで読み込むとAR環境が再現されるようになりました。
ARCore Geospatial APIから取得できるの地球上のGPS座標、近隣のStreetscape Meshを録画し、Unity Editor上で再生することで、家に引きこもりながらARアプリの開発が出来るようになりました。詳しい仕組みについては別記事で解説する機会を作ろうと思います。

この機能により、ほぼ実機で起きるGPS精度起因の問題などをEditorでパラメーターを調整しながら事前に修正することができました。このライブラリの目標の一つであった、 Editorで動くものは実機でも動くEditorで動かないないものは実機でも動かない。 を達成できたと思います。唯一実機で起きたエラーは、メモリが少なくて落ちるくらいでした。

ちなみにARFoundation 5.0以降では、XR Simulationという機能があります。
Simulation Simple AR
任意の3DモデルをUnity Editor上でAR空間としてシミュレーション出来るものです。通常の屋内ARコンテンツを作るときは非常におすすめです。

最後に

普段の仕事で2週間(仕事しながらなのでもっと少ない) でARアプリを作るようなことはないですが、
体験のコア部分だけに集中して作ることで大幅に時間を節約。
実験して良かったものは仕様になくても取り入れる。
バグは夜更け過ぎに仕様に変わる。

というハッカソン特有の制作スタイルでしたが、なにか形にのこり良かったです。
受賞特典の一つであるGoogle AR開発チームとのMTG緊張するな。