Graffity でVisionPro とUnityを用いてゲーム開発をしているcovaです。
今回はVisionPro 向けAR/MRコンテンツを作るにあたって ARPlane(平面検知)
と ARMesh
はよく使われますが、使い方に気をつけないと意図通りの挙動にならなかったトラブルがあったので備忘録として記事化しました。
TL;DR (今北産業)
- Unityで行う場合はARFoundation のフレームワークに則って出来るぞ!
- ARFoundation を使ったことがない方はスマホAR等で利用方法をざっくり理解しておくと良いです
- ARMesh を当たり判定で使う場合はCollider周りの設定を正しく行わないと、意図しない形にCollision用Mesh が変形してしまうので要注意
- ARPlane は普通に使えるし、属性も取れるのでSceneSegmentation/SceneUnderstanding とかにはMeshよりPlaneの方がよかったりします
検証環境
項目 | version等 |
---|---|
Unity | 2022.3.20f1 |
PolySpatial | 1.2.3 |
Xcode | 15.2 |
VisionOS | 1.0.2~2.0beta |
PolySpatial 導入について
以下の内容は様々な方がTechブログで記載されていたり、公式の導入ドキュメントがあるのでそちらをご覧ください
- Proライセンスの設定方法
- PolySpatial をUPMで入れる方法
基本的な使い方
共通の設定項目
Scene 周り
- AR動かす用のコンポーネントを配置しましょう
ProjectSettings
-
AppleVisionOS のところでMR向け設定をしましょう
- InitializeHandTrackingOnStartUp はハンドトラッキングをする場合は必須です
- HandsTrackingUsageDescription はハンドトラッキング利用アプリの初回起動時に表示するメッセージです
- ここが空だとビルドが通らなかったりします
- Info.plist に正しく反映されないままXcodeビルドが通ると実際にアプリを起動しようとしてもすぐクラッシュするなどの問題を引き起こす原因になります
- World Sendsing Usage Description は
入力必須
です- ここを入力しないと
HandsTrackingUsageDescription
と同様の問題の原因になります
- ここを入力しないと
- UpperLimbVisibility は チェックを入れると手の位置と被った3DObjectが存在する場合、自動的にOpaqueでもアルファブレンドで透過する処理をOS側がやってくれます
- ただし透過度合いとかは制御不能でOSが勝手にやります
- 特に必要なければOffでもOKです
-
IL2CPP Large Exe Workaround
は脳死でチェックを入れましょう- Xcodeビルド時にファイルサイズとかのビルドエラーが発生する場合はこれにチェックを入れれば大体解決します
ARPlane
1.XROrigin ObjectにARPlaneManager コンポーネントをくっつけよう
- よくわからなかったらPolySpatial のMixedRealityのサンプルSceneをそのまま利用しちゃうのが楽です
- MixedReality のSampleだとデフォルトでコンポーネントがあるので何もしなくてもOKです
-
- 特に何もなければEverythingで問題ないです
- 壁とか垂直面だけ検知させたいならVertical のみにチェックを入れます
- 逆に水平面だけ検知させたい場合は Horizontal のみにチェックを入れます
-
検知したMeshを可視化させよう
ARMesh
- ARMeshManager Component がヒエラルキーにない場合は追加しましょう. 追加する場合はXROrigin GameObjectにそのままくっつけてもOKです
- Density(密度) は特に指定がなければデフォルトの0.5のままで.
- 密度を上げると頂点数が増えてパフォーマンスにも影響が出るので要注意
- Density(密度) は特に指定がなければデフォルトの0.5のままで.
- Mesh を可視化しよう
ARPlane/ARMesh の応用的な使い方
当たり判定をつける
まず現実空間をスキャンしたらやりたくなること1つ目です。
基本的にはUnityのPhysics系のコンポーネントをシンプルに設定するだけで問題ないのですが、やり方によっては色々トラブルを引き起こす可能性があるので要注意です.
投擲物にRigidbody をつけて当たり判定を実装する場合
- こちらの場合は特に何も気にせず実装できます
- 投擲物側のObjectに Rigidbody と Collider (できればSphereCollider. 次点でBox/CapsuleCollider) を設定
- IsTrigger のOn/Offはどちらでも良いです - ARPlane とARmesh表示用のPrefabそれぞれにMeshColliderを設定する
- ARPlane に関しては厳密さを求めなければBoxColliderで代用も可能
- ARMeshに関してはMeshColliderでないと正しくとれない
-
MeshCollider
のconvex
はOff にしよう- 計算量は増えるが
convex を onにする
と 後述の問題が発生してしまう
- 計算量は増えるが
- ARPlane/ARMesh 側のColliderはできれば
IsTrigger = Off
にしましょう
このようにすれば基本的には現実の見た目とおおよそ一致する場所に当たり判定が生成されます
ARPlane/ARMesh側にRigidbody をつけて当たり判定を実装する場合
コンテンツによっては投擲物の個数が当たり判定Objectより多く出るなんて場合もあります。
その場合はARPlane/ARMesh 側にRigidbody をつけて当たり判定を行わせることで投擲物側の処理コストを下げるというパフォーマンスの稼ぎ方もあります。
その場合ARPlane/ARMesh 側にRigidbodyを追加するのですが、MeshCollider において、Rigidbodyを併用する場合以下の制約があります。
- MeshCollider のConvexフラグをOffにする場合Rigidbody.isKinematic フラグをOnにしないと動かない
- isKinematic フラグをOffだと当たり判定がとれない
- Convex フラグをOnにするとARMeshの当たり判定が見た目通りにならない
ARMeshとMeshCollider のconvex フラグにまつわる問題
Unity のMeshColliderのマニュアルを確認しましょう.
バーチャルキャストさんのTechブログ 等でも紹介されていますが
そこではConvex フラグについて以下のような記述があります.
これを有効にすると、メッシュコライダーは他のメッシュコライダーと衝突します。 Convex (凸状) のメッシュコライダーは三角形面数の上限が 255 に制限されます。
詳細は割愛しますが凸型にすることで当たり判定の計算コストをかなり減らすことができるのtMeshCollider利用した当たり判定をとるときはConvex フラグをOnにします。
一方で、後半の文章にある メッシュコライダーは三角形面数の上限が 255 に制限
が非常に厄介です。
一般的にゲームでMeshCollider はそこまでハイポリのものには使わないです。
(敵キャラの判定も、判定があるところにSphere ColliderやCapsuleColliderを複数置いて、Meshの範囲をカバーするように配置して軽量化を図って実装されることがほとんどです. 主人公キャラ等も胴体、腕、足それぞれにCapsuleCollider を配置で十分なため、MeshColliderは使いません)
しかし、リアルタイムスキャンして取得したARMeshについてはポリゴン数が255を優に超える場合があります。(リアルタイムでMeshのReductionは難しいため)そうするとARMesh にConvexフラグを適応すると、 見た目のMesh
と 当たり判定用のMesh
が 異なる
という現象が生じます。
結果として、何もない空中に謎の当たり判定が生まれるなどの副作用が生じます
現実のものでOcculusion(背後に隠れてるところは見えない)させる
こちらについては以前の記事でも記載しましたが、ARPLane/ARMesh Prefabの各Renderer に設定されているMaterialのShader を AR/Basic Occulusion
にするだけです。
これだけで現実のObjectの背後にあるコンテンツは一部/全体を隠すことが出来ます。
また上記の当たり判定を併用すれば、現実の背後にある敵には、 現実のものが邪魔で攻撃できない
ということが実現可能です。