🐬

【Unity】VisionProサウナ追いととのいアプリの開発知見

2024/12/17に公開

こちらの記事はxRギルド Advent Calendar 2024 の記事です。

サイバーエージェントでエンジニアをしているふしっきーです。

サウナで整った後でVisionProをつけてさらに整う、「追いととのい」プロジェクトのVisionProアプリ開発を担当しました。

追いととのいプロジェクト概要はXR研究所のイワケンが各所で解説してくれているので、この記事では実際のVision Pro開発(Unity)における工夫(大変だったポイント)についてお話します。

「追いととのい」プロジェクトに関しては、以下の記事に詳しく書かれています。
空間コンピューティング時代の没入体験 ─「追いととのう」プロジェクトからの知見─

体験フロー

VisionProをつけて寝転がった状態で、目の前にあるSTARTボタンを押します。
目の前にポータルが出現し、現実空間から水中に遷移し、水中で生き物の間を通り抜けまた現実に戻ってくるという体験です。

https://youtu.be/BM8x26ZTPl0

開発環境

(イベント実施時2024年7月時点)

  • Unity 2022.3.30f1
  • Poly Spatial 1.3.1
  • Vision OS 1.3

Unity選定理由

今回のプロジェクトはUnityを選択しました。理由としては、自分が使い慣れているというのもありますが、Timelineが使えるというのが大きいです。今回の演出はインタラクションはほとんどなく、演出が一方向に再生されるのみなのでTimelineとの親和性が高かったです。

VisionPro開発にUnityを選ぶことで、Unityの機能に制約が発生したもの大変ポイントでした。Swiftなら回避できそうだなと思いを馳せることもしばしば。
Swiftから逃げるな

とはいえUnityだけで開発を進め、イベントで体験したユーザーからは満足度 4.85/5.00 の高評価を得ることができました。

Play To Deviceは必須

今回のアプリ体験はユーザーが上を向く体験なので、開発時実機動作確認のたびに常に上を向く必要があるというなかなかの苦行でした。(首を痛めかけた)

UnityからVisionProシミュレータとリアルタイムに接続できるPlay To Deviceの機能は非常に役に立ってくれました。(おかげで僕の首が守られた)

演出解説

ここからは個別の演出紹介と実現方法について解説していきます。
全部紹介すると膨大な量になってしまうので、主要なものをピックアップしていきます。

※今回の体験は現実空間からバーチャル空間に遷移する体験なので、PolySpatialのApp Modeを「Mixed Reallity - Volume or Immersive Space」に設定しています。

水中表現

視界全体をバーチャルにする表現

よくある表現かと思いますが、内側が表となるCylinderメッシュを作成し、その中で生き物を動かしています。カメラが上昇しているわけではなく、Cylinder自体を下降させています。

ポータル表現

現実空間にの天井にポータルの穴が開く表現

実現の試行錯誤フロー

  • Occulusionを実現するにはShaderLabが必須
    → だがPolySpatialではShaderLabが使えない。。

  • PolySpatialSamplesに同梱されているOcclusionMat(Shader: AR/Basic Occulusion)はどうやら使用できる
    → こちらを使うことに

  • 穴の大きさを可変にしたいが、Shaderをカスタマイズしたら動かなくなる
    → 穴の空いたMeshを用意しOcclusionMatをそのまま適用、Meshを拡大縮小することでポータルの大きさを制御

海の生き物

抽象表現のクラゲ

粒子同士が線で繋がっている表現
Plexusという演出の名称(らしい)

実現の試行錯誤フロー

  • ParticleSysytemとLineRenderを使いたい
    →PolySpatialではLine Rendererが使えない
  • Line RendererをCubeのMeshで代替
    →Particle同士を繋ぐように、個別のparticleの位置をC#で取得しCubeを移動・回転・変形してLineのような振る舞いをさせる
  • ParticleとCubeの位置が合わない
    →Particleの生成システムとC#のシステムが異なるため、合わない
  • Particleは非表示にし、C#で取得したParticleの位置にSphereを描画、Cubeと同じくC#で制御することで位置が合うようになる。

フォーラムで質問

ParticleとCubeの位置が合わない件は、VisionOSのフォーラムで質問したところ、
Replicate Propertiesモードを使っている以上、UnityのC#制御とは別のシステムになってしまうため、位置が合わないとのこと。
フォーラムでの質問、丁寧に対応していただきありがたい。
https://discussions.unity.com/t/the-coordinates-of-the-particles-that-can-be-obtained-from-the-unity-editor-and-the-vision-os-simulator-are-different/370859

魚群

有機的な動きの魚群シミュレーション
particleで表現できない

実現の試行錯誤フロー

  • 通常のシングルスレッドで実装すると非常に負荷が高い
  • 並列処理はUnity DOTS(ECS)を使った実装がよくあるパターン
    →VisionProではECSが使えない!
  • Apple Vision Proはsimd計算(並列処理)ができる
    → C# Job System(並列処理)は使える!
  • C# JobSystemを使った実装に自前で実装
    → シミュレータで動いた時は感動した

その他ハマりポイント

  • ワイヤーフレーム表現で線が細すぎるとジャギる
    → ジャギらない太さを模索
  • 透過オブジェクトが重なると背景が見えてしまう
    → SortingGroupで前後関係を明示的に設定
  • 不規則に発生するParticleの泡表現
    → particle単体だとPolySpatialの機能制限の問題で一様になってしまう、適宜C#でEmitさせバラつかせる

パフォーマンスチューニング

序盤でカクつくタイミングがあり、体験上どうしても解決したかった。

パフォーマンスチェッカーRealityKit Traceでチェックした。
https://developer.apple.com/jp/videos/play/wwdc2023/10099/

明らかに処理負荷が高いタイミングがあったが、どの処理かはRealityKit Traceでは読み解けず。
カクつくタイミングだけはわかったので色々調べたが、どうやらクラゲ(plexus)で使用しているsphereに「sphere collider」が設定されたままになっていて(デフォルトでつく)
これをremoveしたらサクサク動くようになった。
衝突計算してなくてもcolliderついてたら重くなるようでした😇

まとめ

サウナ後の「追いととのい」プロジェクトのVisionProアプリ開発でUnityを選定しました。

現状はまだ技術的な制約があるためやりたい表現をするには工夫が必要でした。
(ゆくゆくは機能やできることも増えていくはず!)
Unityでできる機能増えて欲しい(切望)
とはいえ逆にハックしてなんとか実現するような面白みもありますね。

フォーラムなど質問に答えてくれたり、みんなで助け合う文化がとても良い!
今後もXR盛り上がって欲しいです!

Discussion