[VisionOS開発メモ]SwiftUIのViewだけOcclusionさせなくする方法
概要
VisionOSでは、RealityKitを利用してオブジェクトを生成し表示できます。この時、例えば認識した壁などにオブジェクトが隠れてほしい場合OcclusionMaterialを壁側のオブジェクトに付与してオクルージョンを実現します。ただ、OcclusionMaterialを付与したオブジェクトはRealityView以外のViewやAttachmentで生成したViewに対しても影響してしまいます。そのため、オブジェクトに操作したいSwiftUIのViewが隠れて操作できなくなるということが起こっていました。今回は、それに不完全ではありますが対応した話になります。
オクルージョンで隠れてしまうView
開発環境
- 言語:SwiftUI
- OSバージョン:VisionOS2.1
- Xcode: 16.1
はじめに注意点
今回の方法は、Viewだけオクルージョンしない状態を実現していますが不完全な部分があります。注意点を後半にまとめているのでまた、利用する際にはご注意ください。
結論
結論としては、OcclusionManterialを付与しているオブジェクトに対してを付与することで実現できます。
ModelSortGroupComponentはRealityView配下にあり、EntityとEntityの描画順を設定するComponentになります。UnityでいうところのRenderQueueやuGUIのSortingGroupなどと同じような役割です。
ViewにはEntityがないのでView自身にこれをつけることはできないのですが。OcclusionMaterial側に付与することでViewが手前に表示されることを確認しました。
赤いCubeはオクルージョンしているがViewはその影響を受けていない
実際のコード
// sortingGroupの作成、もしEntity同士で描画順を変えたければ同じgoupを使う
group = ModelSortGroup(depthPass: nil)
// EntityにOccusionMaterialを付与
let entity = ModelEntity(
mesh:.generateBox(
size: SIMD3<Float>(1,1,1)),
materials: [OcclusionMaterial()]
)
// SortingGroupからSortingGroupComponentを作成
// orderはViewだけの場合はなんでも大丈夫
let sortComponent = ModelSortGroupComponent(
group: group,
order: 1
)
// componentをセット
entity.components.set(sortComponent)
// RealityViewに表示
content.add(entity)
ModelSortGroupComponentを付与すると描画順をSourtingGroup内だけで考えることになります。実際に、他のEntityを一緒に表示しても同じSortingGroupではないEntityの描画にはOcclusion Materialは影響しません。恐らくですが、これの副作用としてView側に影響していたOccusionもgroup以外のオブジェクトとして判定されてOcclusioinの影響がなくなったのだと思います。
注意点
最初に話した注意点ですが、
1点目は、ModelSortGroupComponentはRealityKit配下であり、付与されるのはEntityであるためViewへの影響が出るのは公式が意図しているかどうかわかりません。なので、バージョン次第で利用できなくなる可能性があります。
2点目は、ViewをDrag移動させている間はOcclusionの影響を受ける場合があります。現状100%起こっているわけではないですが、結構な確率で下のようにDragしている場合だけOcclusionの影響を受けます。逆に、OcclusionMaterialを付与したオブジェクトをView側に移動させる場合は今のところOcclusionの影響を受けたケースに当たったことはないです。
Viewをドラッグしている時だけオクルージョンしてしまう
終わりに
かなり細かい話でしたが、Occlusionを利用している人は困っている内容だと思うので、不完全ではありますが役に立てれば嬉しいです。
ただ、僕が見つけていないだけでView側のmodifierで一発で影響なくせるよ?みたいなものがあるような気もしており。。もし、もっと簡単で公式的なものがあればご教示いただければと思います。
Discussion