【Unity】Occlusion Portalについて
モデルが非表示になっている部分をスキップすることで3D空間を効率的に描画するOcclusion Cullingという機能の機能の一つ、Occlusion Portalsという機能についてです。
Occlusion Portalsという機能
Occlusion Portalsはマニュアルによると以下のように説明されています。
実行時にオープン・クローズが可能であるオクルージョンプリミティブを作成するには、Unity では オクルージョンポータル を使用します。
実際の動作と仕様が混ざって少し分かりにくい説明ですが、このOcclusion Portalsは要するにOcclusion Cullingによる遮蔽の有効・無効が切り替えられる壁を作る機能です。
どんなときに使えるのか
分かりやすく役に立つシーンは、ドアを開いて屋内に入るようなケースです。試しに下のような画像にOcclusion Portalsを設定してみます。
- 四角い部屋にドアがある
- 部屋の中に色々と物がある
- 部屋の外にも色々と物がある
Occlusion Portalsで、ドアが開いた時に屋内のオブジェクトを表示してみる。屋内に入ってドアを閉じると、屋外は非表示になる #unity pic.twitter.com/zYQlrCbjD0
— 椿 (@tsubaki_t1) 2018年1月6日
まず最初の状態です。部屋の中には物がありますが、Occlusion Cullingが効いているので表示されません。
ドアの向こうには何があるのか分からない状態です。
ドアを空けます。
部屋の中に何があるのかが明らかになります。
部屋に入り振り向きます。
部屋の中と外にある玉を確認することができています。
ドアを閉じます。
部屋の外は確認できなくなるので描画対象から外されます。
このポイントはOcclusion CullingのOccluder(遮る側)を動的に有効/無効を切り替えられる点です。
移動や動的な配置は出来ませんが、ドアのような遮ったり遮らなかったりするような物をOcclusion Cullingで使用する場合に利用できます。
なお、Occlusion Portals内にOcclusion Cullingを作る事も出来ます。例えば部屋ではなく家の場合、外から見る際にはOcclusion Portalsで内側全部を非表示にしておき、家に入ると家内のOcclusion Cullingを起動する…みたいな感じ。
実際に使用してみる
実際に以下のような動きを設定してみます。
簡単なステージの用意
まず下のようなシーンを用意します。
緑のシリンダーが複数存在し、白と赤の壁が遮っています。
OccluderとOccludeeの設定
色分けは、これから行う設定をわかりやすくするために分けています。
- 白:Occluder Staticを設定します。
- 緑:Occludee Staticを設定します。
- 赤:特に何も設定しない。移動する予定の壁
Occluderは遮る側、Occludeeは遮られる側を定義するstaticです。Occludeeは無くとも動作しますが、設定したほうが安定かつ高速な印象です。
Occluderは無駄に設定すると負荷が高くなるので、大きい壁等に使うと良い感じです。
Occlusion Portalsの設定
動く赤い壁(門)の設定です。
この壁はカリングしたりしなかったりするので、Occlusion Portalを使用します。
Occlusion Portalを設定したGameObjectを配置し、範囲を赤い壁を囲うように設定します。(緑色の枠がOcclusion Portalです)
下の図では大げさに範囲を指定していますが、実際にはもう少しタイトな感じに設定したほうが良いです。理由は後述。
Occlusion Cullingのベイク
Occlusion Cullingをベイクします。(Window > Occlusion Culling > Bakeボタン)
シーンが保存されていないと失敗することがあります。
ベイク時にSmallest Occluder(遮るオブジェクトの最小サイズ)が5くらい巨大だと上手く遮られない事があるので、少し小さめな値を設定しておきます。壁の幅は7mですが幅が1mなので1くらいに設定。
ベイクに時間がかかるならOcclusion AreaでOccluderの範囲を限定しとくと良いです。
準備はこれでおしまいです。
開閉のテスト
うまく動作するかをテストします。
動作をテストするにはFrame Debuggerを使用…は最終手段です。まずはOcclusion Cullingの拡張で動作を確認します。
以下の手順で、Occlusion Cullingの表示範囲を判定する為のラインをシーンビューにオーバーレイ表示できます。
- Occlusionウィンドウを表示
- シーンに表示されるOcclusion CullingのウィンドウのEditをVisualizeに変更
- Visibility Linesのチェックを入れる
これでOcclusion Portals開閉の動作を確認します。
Open(初期設定)ではポータルは無効になり、Visibility Linesの線は貫通、壁の向こうにあるシリンダーは表示されます。
逆にClose(チェックを外す)すると線を遮り、奥のシリンダーが表示されなくなります。
壁を遮ってしまうケース
さて、Occlusion Portalはカリング用の壁を作ります。ここで少し疑問がのこります。つまり「赤い壁自体をカリングしてしまわないのか?」という点です。
結論としては遮ります。
概ねのケースでは問題無いでしょうが、運が悪いと赤い壁がカリングされます。そうすると、下の絵のように門の向こう側が見えてしまうといったケースも考えられます。
Occlusion Portalを壁の内側にする
この解決方法の一つはひどく大雑把です。
カリングは「全てのメッシュがOccluderの向こうに存在する」と判断された際に行われます。逆を言えば、一部でも手前に露出しているならカリングされなくなります。
これは単純に範囲外にあるだけでなく、Smallest OccluderやBackface Thresholdなどの値、はみ出てる範囲によっても起こります。
カリング対象外にする
上の方法でも上手く設定できない場合、RendererのDynamic Occludedを外します。これでカリングされなくなります。フラスタムカリングでさえ。
ただ、この設定は最後の手段で出来れば「Occlusion Portalを壁の内側にする」の方法でカリングを無効にしたほうが良い印象があります。
Occlusion Portalの内側に潜り込む問題
「Occlusion Portalを壁の内側にする」方が良い理由は、Occlusion Portalの内側にカメラが入り込む事がある為です。
Occluderの内側にカメラが入り込むと、同一のポータル内で見える範囲しか見れなくなります。
例えばOcclusion Portalの奥と手前・それと中にCubeを置いた時、Occlusion Portalの中にカメラが入り込むと外側のカメラが全て遮られます。
門に使用するOcclusion Portalの範囲を広く設定している場合、門以外のモデルが非表示になる…みたいな事があるかもしれません。
ちなみにOcclusion Cullingでステージの必要な部分が勝手に非表示になる的なやつは、こういった感じでOccluderにカメラがめり込んでるケースが多いです。
屋外・屋内のような切替ではこの挙動は便利かもしれませんが、実際に使う場合には注意が必要な挙動の一つです。
関連
Occlusion Cullingの全体的な紹介
Occlusion Cullingで見える・見えないに応じてスクリプトの処理を切り替えるCulling Groupという機能
Culling Groupの応用で、キャラクターが見える位置に移動したらオブジェクトを生成するアプローチ。