見出し画像

『特定の角度から見たときにオブジェクトが消える!』の解決方法 ~VRChatに適したオクルージョンカリングの使い方~

はじめに

今月のワールド製作者向け記事はオクルージョンカリング(Occlusion Culling)についてです。

日本語で閉塞を意味するOcclusionに、選別するとか間引くという意味を持つCull(ing)で、閉塞を間引く……簡単に言うと、見えないところを非表示にする機能です。

オクルージョンカリングはかなりの有用性を秘めた機能なのですが、VRChat……というよりもそもそもVRでは制御しづらく、『特定の角度から見ると物が消える!』と、ワールド制作初心者を苦しめがちです。

そんなワールド制作初心者のために、今回の記事ではそんなオクルージョンカリングの制御方法をまとめていきます。

オクルージョンカリングについて

まずはオクルージョンカリングについて軽く説明しましょう。

遮蔽物(Occluder)と遮蔽される物(Occludee)をあらかじめ設定し、『この場所からこのオブジェクトは見える or 見えない』というのを事前に計算・保存しておきます。そして、ゲーム内では、その設定に基づいて、プレイヤー(カメラ)の視界に映らないものを消してくれる機能です。

冒頭にも書きましたが、『隠れて見えないものは描画しない』ということをやってくれます。

『え?物の後ろにあるオブジェクトって描画されないんじゃないの?』
という素朴な疑問を持たれる方もいると思います。

実はUnity上では遮蔽されている物体に対しても描画するための処理が走ります。
この時遮蔽されている物体は、基本的に一部の描画処理が省かれるので、見える範囲にそのオブジェクトがある場合と比べて、多少負荷は下がりますが、それでも立派に描画負荷がかかっています。

『それだと常に全て描画されてしまうんじゃ……』
と心配するかもしれませんが、一般的には視錐台カリングと呼ばれる機能によって、私たちの描画範囲は前方一定の範囲と決まっています。

とはいえ、見えていないものを描画するのはコスト的に無駄ですよね?
それを解決してくれる機能、それがオクルージョンカリングです。

基本的な使い方

まずは基本的な使い方を簡単に説明します。

最初に各ゲームオブジェクトに対して、遮蔽物(Occluder)なのか、遮蔽される物(Occludee)なのかのフラグを付けます。各ゲームオブジェクトの右上にあるStaticフラグの右側のドロップダウンをクリックすると、Occluder StaticとOccludee Staticという項目があります。
(余談:どっちがどっちだっけ?となりやすいと思います。自分は2つの語尾で、『ダー』が『ディー』より強そうな響きなので、「強いやつ(ダー)の後ろに隠れる(ディー)」と覚えています……しょうもないですが)

これにチェックを入れることでフラグを付けることが出来るのですが、Staticと名前がついている通り静止物体(動かしたり、非表示にしたりしない)のオブジェクトにのみ、設定してください。
一応OccluderとOccludeeのフラグは両方付けることが出来て、その場合遮蔽する側にもされる側にもなります。

一通り設定した後に上のメニューから[Windows]→[Rendering]→[Occlusion Culling]でオクルージョンカリングのウィンドウを出します。

Bakeタブにある設定項目を設定して、Bakeボタンを押すことで、事前計算が行われ、オクルージョンカリングが効くようになります。
各種設定項目については、既存の記事が結構ありますので、そちらを参考にしてみてください(これとか、これが良いかもしれません)

動的オブジェクトのカリング


動的(=動きのある)オブジェクトはカリングできないの?という疑問があるかもしれませんが、デフォルト設定だとオクルージョンカリングでカリングされます。

Renderer系のコンポーネント(Mesh RendererやSkined Mesh Rendererなど)の設定をよく見ると、Dynamic Occlusionという項目があります。この項目をオンにしていると、動的オブジェクトであってもカリングされます。

Dynamic OcclusionはデフォルトでONなので、この項目を意図的にOFFにするようなことが無ければ、個々人がアップロードしているアバターもカリング対象になります。アバターの負荷は場合によりますが、小規模なワールド1個分以上の場合がありますので、実にパフォーマンス的にお得です。

ちなみに私が知っている限りですが、ワールド製作者側が簡単にアバターのカリングを行う方法はこれしかないので、是非使っていきましょう。

オクルージョンカリングの問題点

残念ながらVRChatにおいて、オクルージョンカリングは相性が悪いと言っていいと思っています。

何故なら、私たちはPlaySpaceMoverやSpace Drag等を併用して、ありとあらゆる場所・角度からオブジェクトを見ることが出来るからです。
コライダーがあろうと関係なく、壁に視点をめり込ませて、何があるのか覗くことが出来てしまいます。

その結果、オクルージョンカリングの精度が甘い角度から見たときに、オブジェクトが見えているにもかかわらず消えてしまう現象をプレイヤーは目の当たりにしてしまいます。

Occluderの中にカメラを入れる前
入れた後

一般的なゲームだと衝突判定によって、プレイヤーが移動できる範囲と目にできる光景というのは決まっているので、オクルージョンカリングの調整によって何とかすることが出来ますが、全方向ありとあらゆる視点から完璧にするのは、まず無理でしょう。

恐ろしいことに、遮蔽物の内部から見たときの挙動はなんと未定義らしいです。つまり、どんな結果が返ってきてもおかしくないということです。
(実際上に貼った画像ではOccluderの中に視点を入れると、色んなものがカリングされています)

そのため、使い方を工夫して、なるべくプレイヤーの視点を遮蔽物の中に入れさせないようにする必要があります。

VRChat内でのオススメの使い方

さて、『プレイヤーの視点を遮蔽物の中に入れない』ということを考えたときに、シンプルな解決方法があります。

それは「絶対にプレイヤーが行かない場所にOccluderを設定する」ということです。

『さっき、PlaySpaceMoverとかSpace Dragとかで壁の中覗くから相性悪いって言ってたじゃん!』
と思うかもしれませんが、それは壁や地面自体にOccluderを設定している場合の話です。そうしてしまうと、壁や地面に視点を近づけただけでオクルージョンカリングが暴発してしまいます。
(2023/10/18 追記 どこかのバージョンで強化されたのか分かりませんが、壁に近づいても暴発しなくなっていました……以下の方法は暴発してしまい、困るときとかに参考にしてください。ちなみにパラメータはSmallest Occluderが1、Smallest Holeが0.1で試しました)

なので、「地面や壁の奥深くにOccluder用のオブジェクトを配置する」ことで、オクルージョンカリングの暴発を回避します。

少し、図を使って解説しましょう。

上の図のように、二つの部屋を一つの壁が区切っているケースを考えます。
壁自体にオクルージョンカリングを設定すると、赤く塗った場所辺りに近づいただけで破綻してしまうことが大半です。

そこで壁の中に、Occluder専用のオブジェクトを作ります。その際、壁から距離をあけてオブジェクトを置くことで、オクルージョンカリングが破綻するエリアを壁の中に隔離することが出来ます。これにより壁に近づいても破綻することはなくなるので、オクルージョンカリングの平和的利用が出来ます。

ソファーや椅子といった部屋の中に配置するオブジェクトにOccluderを設定すると、いとも簡単に『特定の角度から見ると消える』現象が起こります。プレイヤーが行ける位置にOccluderを設定するのは避けたほうが良いです。

そのため、部屋の中にあるオブジェクトにはOccludeeのみを設定し、Occluderを設定するのは地面や壁の中のOccluder専用オブジェクトだけにします。このように厳密に決めてあげることで、暴発の危険性はぐっと減ります(オクルージョンカリングの設定にもよりますが)

さらに、オクルージョンカリングは事前計算なので、遮蔽物はBakeボタンを押すときのみ存在すれば問題ありません。なので、Occluder用のオブジェクトのタグをEditor Onlyにしてあげることで、アップロードするときに自動的に除外することが出来ます。

注意点としては、壁と壁の間があまりにも狭く、十分に距離を取ることが出来ない場合は暴発する可能性があるので、そのような場所ではOccluderを配置しないほうが良いでしょう。

また、カリングはオブジェクト単位で行われますので、メッシュが一部分でも視界内にあると全て描画されてしまうので、適切に小さく分割するということも必要なケースがあります。MeshBakerなどでまとめていると効き目が悪くなる場合があるのでご注意を。

勘のいい方はお気づきかもしれませんが、構造的にオクルージョンカリングを効かせやすい構造というのがあります。
例えば曲がりくねっていて先が見通せない通路などは、非常にオクルージョンカリングを使いやすい構造です。大量のオブジェクトを配置したい場合など、あらかじめ高負荷になることが予想されるなら、オクルージョンカリングしやすい構造にするのは良い手だと思います。
(ShaderFesとかの通路はそんな感じだと思います)

仕様……?

オクルージョンカリングの計算を行った後にオブジェクトを配置した場合、Occluderの設定を先ほど記載した通りに行っても、特定の角度から見たときに見えなくなることがある気がします。

新しく配置したオブジェクトにOccludeeを設定してあげて、再度Bakeしてあげることで問題なくなるはずです。

おわりに

というわけでオクルージョンカリングについて解説しました。

市販のアセットとかは既にオクルージョンカリングが設定されていて、何も知らずに買った初心者が苦しめられている様子をたまに見かけます。

上手に使うと力強い味方になってくれるので、この記事を読んで上手く使いこなす方法を身に着けていただけたら幸いです。

長文読了お疲れ様でした。

この記事が気に入ったらサポートをしてみませんか?