VRChatライティングファストマニュアル(Unity2019対応)

みなさんこんにちは、MinaFrancescaです。
前回のライティングに関する記事はUnity2018までのもので、2021/12/26現在はUnity2019を使うルールとなっております。そのためライティングとそれに関連してくる様々な設定を、細かい説明は抜きにして「こうすればうまくいく!」というていで、Unity2019対応として改めてご紹介していきます。
ワールドは私のHOMEワールド「みーなさんち」を使って説明していきます。

◆この記事について

  • なぜこうする必要があるのか?というお話は最小限にして、タイトル通りファストマニュアルを目指します。
  • ライティングに関する様々なマニュアルが既に世の中にたくさんありますが、それらでは紹介されていない、あるいはそれだけでは足りない部分を補っていきます。
  • ライティングだけでなくそれに関連するワールド作成のポイントもご紹介していきます。

それでは下記の項目順に説明していきます。

◆目次

・ヒエラルキーの整理整頓
・綺麗なLightmapを焼く
・アバターの見た目を考慮したライティング
・オキュリュージョンカリング
・リフレクションプローブ
・PostProcessing
・室内と室外のライティングの変化
・Lightmapが綺麗に焼けるMeshBaker設定
・Realtime(Mixed)ライトも上手に使う

開発環境は下記の通りです。
Unity 2019.4.31f1 (64-bit)
VRCSDK3
CyanTriggerを利用しています

ヒエラルキーの整理整頓

まずはライティング本編に入って行く前に、ちょっとお節介をさせてください。
ご自身のUnityのヒエラルキーをいまいちど眺めてみませんか?ヒエラルキーの整理整頓は、小さなプロジェクトではさほど問題になりませんが、配置するオブジェクトが多くなればなるほど、あとから管理が大変になってきます。
私はこちらのアセットを利用しています。
Rainbow Hierarchy 2
https://assetstore.unity.com/packages/tools/utilities/rainbow-hierarchy-2-106670?locale=ja-JP

具体的にどんなことが出来るのかというと、階層になる部分に点線が付与されるのと、ゲームオブジェクトにアイコンを設定できます。
また、上の画像では目のマークのアイコンが非表示になっています。これはビルド時に非表示にしておくべきオブジェクトを指しています。こうすることで後から「あれ?これは出しておくんだっけ?消しておくんだっけ?」と迷うことが無くなります。

次に命名規則を自分の中で決めて、出来る限りそれを守っていくことを心がけましょう。私の場合はパスカルケース(先頭を大文字)です。上記画像では見えませんが、さらにアンダースコアやハイフンをうまく使い分けると便利です。
例として、「Lighting-Night / Lighting-Day」など。

そしてそれぞれを空オブジェクトで、いわゆるフォルダ分けされているような状態を作ると美しいヒエラルキーとなるでしょう。ワールドのセッティングに関するもの、ライティングに関するもの、サウンドに関するもの、といった具合に分けて整頓しましょう。

綺麗なLightmapを焼く

Lightmap Parametersを作成します。
Lightmap Parametersをこのように設定します
MeshRendererコンポーネントのScale In Lightmapを10に設定します
ヒエラルキーでMeshRendererと検索すると、MeshRendererコンポーネントが付与されているオブジェクトを一括で選択、設定変更できます。
モデルのインポート画面。赤枠部分のように設定します。
skpモデルの場合です。赤枠のように設定します。
こちらはfbxやobjモデルの場合です。赤枠のように設定します。

Generate Back Face
メッシュの裏面が無くて透明になって困る場合は「Generate Back Face」にチェックを入れます。 

Generate Colliders
コライダーを設定する予定がある場合は、こちらをチェックしておくと、あとから大量にコライダーを設定する必要がなく便利です。

Mesh Compression
メッシュを圧縮して軽量化する設定です。圧縮率は微妙ですが通常Highで大丈夫です。
稀にこの設定によってメッシュが破綻したり、ジラジラと重なっているかのような見た目になってしまう場合があります。見た目がおかしいな?と思ったらこの設定を疑ってください。

PointLightを配置しましょう。

Lightは、オブジェクトの中に埋もれないように配置します。
通常は「No Shadows」の設定で大丈夫ですが、味のある影、ホラワなどのボソボソとした感じがお好みであれば「Soft Shadow」を使ってみるのも良いかもしれません。

PointLightをたくさんおいていくと、何故か光ってくれないLightが出てきます。
こちらの設定を参考にしてください。Pixel Light Countが低く設定されていることが原因です。
これはプレイヤーの視界内で一度に処理してくれるライトの数で、多くすればするほど負荷は高まります。しかし結局はBakeするので、いったん大きい数値を設定しておきます。50くらい。
ただし、フィールドが広く、Realtimeのライトを広範囲に置いている場合は注意が必要です。
ものすごい遠いところまで多くのライトを処理してしまうことになり負荷となりますので、その場合は10~20くらいの適切な数値を入れます。

焼きたいオブジェクトをStaticにします。

闇雲にすべてをStaticにするのではなく、Contribute GIにチェックを入れるだけでもBakeの対象になります。動かす予定のもの、例えばドアやコップなど。こういったものはContribute GIのみにチェックを入れます。鏡面反射させたい場合はReflection Probe Static もチェックを入れます。

画像のように設定します。
画像のように設定します。

Lightmap Resolution / Lightmap Size
こちらは仕上げの場合の数値です。開発段階では、「5 / 512」くらいで十分です。

Lightmapper
Progressive GPU(Preview)に設定します。グラフィックボードで焼くのでとても高速です。
対応していないグラフィックボードをお使いの場合は、Bake時にここが勝手にCPUに設定しなおされてしまいます。勝手に設定が変わってしまってGPUでBakeが始まらない場合は、新しい高性能なグラフィックボードの購入を検討しましょう。

Directional LightはBakeしません。

いまだにDirectional LightをBake設定にしてしまうケースがあるようですが、例えば40人オーバーの人数が一斉に集まるような会場であればパフォーマンスを得られて有用ですが、それ以外では通常Directional LightはBake設定にはしません。
Bakeしてしまうと以下のような問題が起こります。

・水シェーダーが機能しない
・アバターが真っ暗
・アバターの影が出ない
・樹の影や草の影が動かない
・樹や草が黒くなる
・Bakeに時間を要する、あるいは正しくBake出来ない

Directional Lightを焼くとパフォーマンスは向上しますが、ビジュアルがかなり損なわれます。
アバターのシェーダーが闇鍋状態のVRChatでは、アバターが真っ暗になってしまってワールドを気に入ってもらえなくなってしまう原因にも繋がります。
LightProbeを利用して事前計算させる手法もありますが、これもアバターのシェーダーによってその影響の受け具合はまちまちです。ライトが無いところに行くと急激にアバターがまっくらになってしまって、特定位置に立ち続けた経験はありませんか?
VRChatの必死の最適化により、Directional Lightを焼かなくても十分90FPSに到達するワールドを創ることが可能です。なんでもかんでもBakeするのはモバイル向けのお話です。

アバターの見た目を考慮したライティング

左がNonPlayer 右がPlayerの設定です。

Directional Lightを2つ用意して、それぞれワールド用とアバター(プレイヤー)用とで使い分けることで、背景に埋もれないアバターの明るさを保持できます。

ワールド全体に適用されるDirectionalLightです。
ただしCulling Maskの設定でこれらのチェックを外します。
アバター(Player)用のDirectional Lightです。これらにチェックを入れます。

こうすることで、ワールドとアバター(プレイヤー)とで別々の明るさを設定できます。

実際に自身のアバターを配置し、レイヤーをPlayerに設定してみましょう。

アバター(プレイヤー)が心地よい明るさで見えるように、アバター用のDirectional Lightの明るさを調整しましょう。
Culling Maskによって光の及ぶものを制御しているので、Directional Lightを2つ置いたから負荷が2倍、なんてことにはなりません。ご安心ください。

オキュリュージョンカリング

オキュリュージョンカリングは、「Occlusion Area」というコンポーネントをCubeに付与し、設定したい範囲をこの画像のように覆ってください。
闇雲に全体をオキュリュージョンカリングBakeしてしまうと、ワールド容量が大きくなってしまいます。

室内がある場合は2くらいで良いでしょう。広いフィールドの場合は5~10くらいです。

リフレクションプローブ

鏡のようなオブジェクトや、反射して背景が映り込むようなオブジェクトがある場合は、ReflectionProbeを配置しましょう。

後ろのスタンドミラーにご注目ください。反対側の本棚が映り込んでいます。

とても現実味が増しますのでぜひ設定しましょう。

PostProcessing

 

Nearを0.01に設定しましょう。ガチ恋距離設定です。必須です。マストです。これによって育まれる愛がVRCにはあります。
PPSという空オブジェクトを作成して、Post Process Volumeのコンポーネントを付与します。

レイヤーを先ほどのTransparentFXに設定するのをお忘れなく。これで画面効果がかかります。

VRCWorldのPrefabを配置していることと思います。
Reference Cameraの設定にMain Cameraを必ずセットしてください。
VRChatにアップロードした時に、この設定が空のままだと画面効果がかかりません。

街灯はぼんやりと光ると良い感じです。
眩しくしすぎると苦情がくるので注意しましょう。

室内と室外のライティングの変化

室内に入る時と出る時でアニメーションを設定し、スムーズにライティングを切り替えます。

アニメーションによってPostProcessのGlobalのスライダーが動いていることに注目してください。
これによって室内と室外のライティングをスムーズに切り替えます。
入り口付近にIsTriggerのコライダーを配置し、CyanTriggerでプレイヤーとの接触判定を取ります。
ここではAnimatorのtriggerに、出た時と入った時とで0と1を代入しています。

triggerが0の時と1の時とでステートを移動します。これによりAnimationClipを出し分けて、室内と室外とでライティングを分けています。

ちなみにリスポーンして瞬時に外に出た場合を想定して、resetというトリガーを作り、瞬時にステートを戻す処理も忘れずに入れておくとよいでしょう。

その場合、リスポーン地点にIsTriggerのコライダーを置き、ここでAnimatorにresetのトリガーを引くようにCyanTriggerで設定します。

プレイヤーの接触判定によってresetのトリガーを引き、なおかつtriggerの数値を0に戻します。室内だけのワールドでは必要ありませんが、お外に素敵なお庭を作りたい!という場合には有用です。

Lightmapが綺麗に焼けるMeshBaker設定

残念ながらこちらの設定をもってしてもうまく焼けないケースは十分にありますが、私の経験上もっとも成功率の高い設定です。お悩みの方はぜひお試しください。

ワールド制作の場合は「TextureBaker and MultiMeshBaker」を使います。
対象オブジェクトを設定する画面です。

Exclude meshes with out-of-bounds UVsのチェックを外します。

正しくオブジェクトが設定されたかを確認します。
Create Empty Assets For Combined Materialのボタンでassetを作成します。
Multiple Combines Materialにチェックを入れて、すぐ下のボタンを押します。

ここがポイントです。多くのMeshBaker関連の記事で紹介されない部分です。
Consider Mesh UVsすべてにチェックをいれます。
最後にBlend Non- Texture Propertiesにチェックを入れて、紫色のボタンを押します。

最後はおなじみの設定です。

以上で、最後に「Bake All Child MeshBakers」を押します。
何か問題がある場合は押しても一瞬で処理が終わってしまったり、エラーがログに出現したりします。

まとめたMeshがこのように出力されます。
Scall in Lightmap を10に設定するのをお忘れなく。

MeshBakeが終わったあとに残ったMeshBakerのゲームオブジェクトは消しても良いのですが、あとでまた同じ設定で利用したい場合もあるかもしれません。
また、MeshBakeする前のオブジェクトは、念のためバックアップでとっておくと安全です。
しかしそのままではビルド時にこれらも含まれてしまいワールドサイズに加算されてしまいます。
そこで赤枠部分を「EditorOnly」に設定します。これでビルド時にはこれらのオブジェクトが含まれなくなりますので便利です。

一度Lightmapを焼いてあるものをMeshBakeすると上の画像のようにLightmapの画像が紐づいてきたりしますが、これはMeshBakeした結果のオブジェクトには適合していないので、一度Lightmapをクリアして再度Bakeしなおす必要があります。

LightmapのデータはScene名と同じフォルダが生成されてそこに保存されています。
赤枠部分にチェックを入れ、クランチ圧縮をしましょう。
それでもファイルサイズが大きい場合はMaxSizeを512くらいまでは落としても大丈夫です。

Reflection Probeも同じ場所に生成されています。こちらも赤枠部分にチェックを入れてクランチ圧縮しましょう。

Realtime(Mixed)ライトも上手に使う

ライトは全部ベイクするんだ・・・!という謎の使命感、義務感に囚われていませんか?
実はRealtime(Mixed)のライトもとても有用ですし、Bakedライトでは表現できないことが多々あります。
ここではそのいくつかの設定例をご紹介します。

例えば水面に浮かぶ、あるいは半分くらい沈んでいるクリスタル。Bloomで処理しても良いのですが、水面にぼやぁっと青い光が当たると、水面がとても綺麗になります。
青いPointLightを置くとこのように綺麗な水面を表現できます。

Realtimeのライトは負荷が高い、という認識は間違いではありませんが、使い方をしっかりわきまえれば、負荷は最小限に絵心あるビジュアルを生みだせます。

赤枠部分に注目します。
RealtimeでもMixedでもどちらでも構いません。
Rangeが極めて小さい数値です。その代わりにIntensityがかなり高い数値です。
Rangeは広げれば広げるほど負荷がグングン高まりますが、Intensityはどんなにあげても負荷は高くなりません。
ShadowTypeはもちろんNo Shadowsです。
そして最後にCullingMaskのプルダウンを確認しましょう。

Player、PlayerLocal、MirrorReflectionのチェックを外します。これでアバターにはこのライトが及ばないため負荷としてはだいぶおさえられますし、Intensityを高めに設定していてもアバターには及ばないためアバターが真っ白になる、なんてこともありません。
水面にだけ光を反映させたいのであれば、WaterのレイヤーだけにチェックでもOKです。

こちらの場合はどうでしょう。地面に置くタイプのお洒落照明ですが、現実世界であれば周囲の地面がぼんやりと明るくなるはずです。
残念ながらTerrainのLightmap焼き付けは私はあまりお勧めしません。Terrainひとつだけのワールドであればさほど気にすることはないのですが、複数個存在する場合で、あちこちにこういった照明や街灯が点々と存在する場合、Bakeする時にTerrainを全部表示状態にしてLightmapを焼かなくてはいけなくなり、ファイルサイズが増えてしまいますし、Bake時間も膨れ上がります。
また、2Dテクスチャの草を生やしている場合、草は焼けませんし、樹々を焼こうとすると樹々は真っ黒な葉を実らせてしまいます。

そこでRealtimeライトの出番です。先ほどの水面のクリスタルと同様に、Rangeを極めて小さくし、Intensityを高く設定します。

Rangeは1です。とても狭い範囲なので負荷もかなり抑えられています。

TerrainはEnvironmentのレイヤーなので、このようにCullingMaskのプルダウンでEnvironmentだけにチェックを入れます。
こうすることでTerrainにしか光が及ばないので、負荷をかなり最小限に出来ます。

ですがもちろん使いすぎは禁物です。広く見渡せる場所でこれを多用するとすぐにSetPassCallsが跳ね上がります。

◆編集後記

以上でUnity2019対応版ライティングの記事とさせていただきます。いかがだったでしょうか。
Google検索ですぐに見つかるライティング記事では、残念ながら情報が不足しています。より多くの方が自由にのびのびとUnityのライティングを楽しく行えるよう、今回Unity2019対応版として新しく書かせていただきました。
また、CyanTriggerとAnimatorを使った室外と室内のライティング切り替えの仕組みや、そもそもBakeしないという選択肢。
何もかも必ずBakeしなければならない、というわけではなく、素敵なビジュアル、景観を創り出すために、Realtimeのライトも賢く使うのです。

それから今回もBakeryに関する内容は省かせていただきました。というのも、Unity2019になってGPUでのBakeがよりスムーズに行えるようになったため、ますますBakeryを使う意味は薄れました。また、Bakeryで焼こうとするとMeshのUVがなんかおかしいぞ!みたいなダイアログが何度も出てきたり、焼いてる途中の画面が見えないし操作も出来ない、という不便さがあります。設定でなんとかなることもありますが、そもそもPointLightに全部Bakery用のPointLightコンポーネントを追加で設定しなければならないのが面倒です。
VRChatのワールドに行って、これはBakeryで焼いてるな!なんて見分けは絶対につかないでしょう。Bakeryじゃなくても綺麗にLightmapは焼けます。断片的な情報に惑わされずUnity標準機能をまず最大限利用していくことをおすすめします。

ライティングはとても楽しい工程です。素っ気なかった景色がグンと見栄えするものになっていく工程です。設定項目や覚えなきゃいけないことは確かに多いのですが、まずはこの記事で紹介されているままにライティングにチャレンジしてみましょう。
より多くの方がVRChatで素敵なお部屋やお庭を手に入れられるよう、本記事をぜひ多くの方とシェアをお願いいたします。
それでは楽しいVRChatライフを。

MinaFrancescaでした。