はじめに
この記事では自分が VRChat のワールドを制作したときにそのワールドの負荷を減らすためにしたことをメモしておきます。
最適化の方法
GameObject の static 化
まずは GameObject の static 化(静的化)です。
ゲーム中に動くことのない GameObject を選択してインスペクターの右上の「Static」にチェックを入れるとその GameObject をゲーム中に絶対に動かない GameObject として登録できます。
これによって無駄な計算が減って負荷が少し軽減されます。

メッシュの圧縮
次はメッシュの圧縮です。
これは単純にメッシュの頂点数が多いままだと負荷が大きいのでメッシュを圧縮して頂点数を減らすというものです。
方法は非常に簡単で Assets フォルダ以下にある3Dモデル(FBX など)を選択してインスペクターの「Model > Meshes > Mesh Compression」を Off から Low や Medium、High に変更するだけです。

テクスチャの圧縮
次はテクスチャの圧縮です。
これはワールド内のメッシュや UI などにアサインされているテクスチャの解像度を落とすという作業です。
こちらも方法は簡単で Assets フォルダ以下にあるテクスチャを選択して「Max Size」を変更するだけです。

ライトベイク
次はライトベイクです。
これは光の反射や影の描画に関する計算をリアルタイムで行うのではなく、事前に計算しておくという手法です。
全てを事前に計算しておくのでもしゲーム実行中にライトや GameObject を移動させても影や光の表現はそのままになります。
(ライトベイクの対象にするライトや GameObject は static にする必要があるのでゲーム中に動かすことはないかと思いますが…)
方法は簡単で、ゲーム実行中に絶対に動かない GameObject を static にして「Window > Rendering > Lighting Settings」で Lighting ウィンドウを開いて「Generate Lighting」を押すだけです。


この Lighting の設定に関しては高千穂マサキ様の「ライトベイクの基本を学ぼう」という記事が非常に参考になります!
オクルージョンカリング
次はオクルージョンカリングです。
これはプレイヤーの視界の外にある GameObject や他の GameObject に隠れている GameObject は描画しないというものです。
オクルージョンカリングの使い方に関しては以下の記事が参考になるかと思います。
「Window > Rendering > Occlusion Culling」で Occlusion のウィンドウを開いて Bake というタブでいろいろと設定を行った後に「Bake」を押すだけです。


Dynamic Materials の削除
次は Dynamic Materials の削除です。
VRChat ではワールドで使用されているマテリアルは全て VRC Scene Descriptor の Dynamic Materials という配列に追加されるのですが、既にワールドでは使用されていないマテリアルが登録されたままになってしまっていることがあるのでそれらを削除します。
手順は以下の通りです。
- ヒエラルキーで「VRCWorld」を選択します
- インスペクターの「VRC Scene Descriptor > Dynamic Materials」からワールド内に無いマテリアルを削除します

メッシュベイク
次はメッシュベイクです。
複数のメッシュを1つにまとめるやつです。
ワールド全体を1つのメッシュにまとめると視錐台カリングやオクルージョンカリングが実質的に機能しなくなるのである程度はメッシュを分けておく必要があります。
メッシュベイクの方法はいくつかありますが、Mesh Baker などのツールを購入してメッシュベイクするか、Blender などの別のソフトでメッシュを結合する感じになるかと思います。

その他(小技?)
ここからは小技?というかちょっとしたテクニックを紹介します。
鏡
まずは鏡についてです。
VRChat に限らず「メタバース」というのはアバターが非常に重要な要素であり、鏡で自身の姿を眺めていたいという需要や、鏡の前で友達とツーショットを撮りたい!といった需要がかなりあるので鏡の設置はかなり重要になってきます。
しかし、鏡面反射の処理は非常に重たいので鏡に関してはかなり頑張って最適化する必要があります。
例えば以下の方法があります。
- 特定の Layer の GameObject だけ映り込むようにする
- 「VRC_MirrorRiflection > MaxAntiAliasing」を 1~4 ほどまで下げる
- なるべく GameObject が映り込まない位置に鏡を置く
- 鏡の初期値をオフにしておいて各プレイヤーがオンオフを切り替えられるようにする
- 鏡を Camera と RenderTexture で代替する
その他
その他の小技は以下の通りです。
- VRC_Trigger ではなく、Unity の Animator の遷移で状態を作るようにする
- 複雑な頂点数の多い3Dモデルには LOD を設定する
- 同じ構成のオブジェクトはプレハブ化する
- MeshColider は使わずに BoxCollider などの基本図形のコライダーの組み合わせで代替する
最後に
参考記事
- 【VRChat】自作ワールド作りました! いろいろメモ(作業手順、UdonSharp、軽量化など)
- ワールド最適化
- オクルージョンカリングを設定して、ワールドの軽量化をする
- ライトベイクの基本を学ぼう