Unity:ライトマップデータをゲーム実行中に切り替えてライティングを変える

スポンサーリンク

今回はライトマッピングを使用した室内シーンの照明でゲーム実行中にライトマップデータを差し替えてライティングを変更する方法を試してみました。

シーンのライティング

ライトマップをベイクする Area Light のみを使用して明るい照明と暗い照明を配置したテスト用のシーンを用意します。ライトプローブとリフレクションプローブを配置しています。

明るい照明はややオレンジ色に調整してこんな感じになりました。

暗い照明は床に配置して色をグリーン調整。こんな感じになりました。

Lighting 設定について

ライティング設定は WebGLビルドに合わせて調整。
メニュー:Window > Rendering > Lighting Settings を選択。[Lighting]ウィンドウ > [Scene]タブを選択。シーンは室内のみでライトプローブとリフレクションプローブを配置しているので環境ライティングは影響を失くし、WebGLビルドでサポートされていない Realtime Lighting のチェックは外します。

Lightmapping Settings > Directional Mode もWebGLビルドでサポートされていないので通常は Non-Directional に設定しますが。今回はスクリプト検証のために Directional に設定しました。

WebGL グラフィックス – Unity マニュアル
Unity WebGL は Baked GI のみをサポートしています。 Realtime GI は WebGL では今のところサポートされていません。なお、Non-Directional ライトマップのみがサポートされています。

ライトマップ – Directional Mode – Unity マニュアル
Non-Directional ライトマップは平らな拡散を生成します。このモードはただ 1 つのライトマップを使用しており、光が純粋に拡散性であると仮定して、どれだけ多くの光を表面から放出するかという情報を保存します。オブジェクトはこの方法で照らされると、平らに見えます (法線マップは使用されません)。

ライトマップデータの出力

明るい照明の状態から暗い照明に切り替えるにはライトマップデータを書き出し、ファイルを差し替える処理を行います。そこでシーンを暗い照明の状態にしておき、ライトマップデータをファイルに書き出します。

ライトマップファイルの出力

[Lighting]ウィンドウ > [Scene]タブ > Auto Generate チェックを外し、[Generate Lighting]ボタンをクリック。

シーン名と同じフォルダが作成されて、ライトマップファイルが出力されました。

ライトプローブファイルの出力

先程出力したライトマップデータにはキャラクターのように動くオブジェクトにライティングを反映するライトプローブファイル含まれていません。調べてみると、ライトプローブファイルはアセットファイルとして現在のシーンから個別に出力する必要があるということなので、エディタ用スクリプトを作成します。

ビルドの際にエディタ用スクリプトを除外するために新しく Editor フォルダを作成します。 [Project]ウィンドウ > [Create] > Folder を選択。名前をEditor に変更。フォルダをダブルクリックして階層を移動してから [Project]ウィンドウ > [Create] > C# Script を選択。

メニュー項目に Export が追加されました。スクリプトファイルを作成するだけでメニューを拡張できるとは、ちょっと不思議な感じです。

追加されたメニュー:Export > ExportLightprobe を選択すると現在開いているシーンのライトプローブがシーン名と同じフォルダにアセット(拡張子 asset )として書き出されます。

ライトマップデータの複製とリネーム

出力したライトマップデータから法線ライトマップ、ライトマップ、リフレクションプローブを複製(Ctrl キー + D キー)し、別ファイルにしてからリネームします。

このようにリネームしました。

  • ライトマップ:Lightmap-0_comp_light 1 → Lightmap-Dark_comp_light
  • 法線ライトマップ:Lightmap-0_comp_dir 1 → Lightmap-Dark_comp_dir
  • リフレクションプローブ:ReflectionProbe-1 → ReflectionProbe-Dark
  • ライトプローブ:Lightprobe → Lightprobe-Dark
ライトマップデータを複製せずにそのままリネームすると [Lighting]ウィンドウ > [Scene]タブ > Auto Generate チェックを入れたとたんにライティング計算が始まりファイルが削除されてしまいます。

明るい照明のライトマップデータを出力

暗い照明のライトマップデータの出力ができたので、シーンを明るい照明に戻し、 [Lighting]ウィンドウ > [Scene]タブ > [Generate Lighting]ボタンをクリック。元のライトマップデータは上書きされます。リフレクションプローブだけ複製します。
メニュー:Export > ExportLightprobe を選択して明るい照明のライトプローブを出力します。

このようにリネームしました。

  • リフレクションプローブ:ReflectionProbe-1 → ReflectionProbe-Bright
  • ライトプローブ:Lightprobe → Lightprobe-Bright

出力したすべてのライトマップデータを新しいフォルダ LightmapData を作成して移動します。必要なライトマップデータが揃いました。

ライトマップデータを切り替えるスクリプトの作成

ライトマップデータを切り替えるオブジェクトとスクリプトを作成します。

スクリプトを割り当てるオブジェクトの作成

[Hierarchy]ウィンドウ > [Create] > Create Empty を選択。名前を Corevale_SwapLightmap に変更。[Inspector]ウィンドウ > [Add]Component]ボタンをクリック。新しいスクリプトファイル SwapLightmap を作成します。

スクリプトの編集

スクリプトの内容はこのようになっています。UIのトグルボタンでライトマップデータを切り替えるための処理を入れています。

コンポーネントの設定

スクリプトが完成したので設定を行います。

SwapLightmap (Script) コンポーネントの設定

スクリプトを割り当てたオブジェクト SwapLightmap を選択して[Inspector]ウィンドウで確認するとこのように変数と配列のフィールドが表示されています。

配列数を変更して表示されたフィールドにそれぞれライトマップデータのファイルを割り当てます。Probe Component フィールドにはシーンに配置してあるライトプローブオブジェクトを割り当てます。

ReflectionProbe コンポーネントの設定

リフレクションプローブのコンポーネントの設定はデフォルトでType > [Bake]になっています。(シーンの静的オブジェクトをベイクしたキューブマップを使用)
スクリプトからリフレクションプローブのキューブマップファイルを切り替えるために設定を[Custom]に切り換え、明るい照明のリフレクションプローブ ReflectionProbe-Bright を割り当てておきます。

UIオブジェクトの作成

ライトマップデータを切り替えるためのトグルボタンを作成します。[Hierarchy]ウィンドウ > UI > Toggle を選択。
[Inspector]ウィンドウ > Toggle (Script) > On Value Changed (Boolean) にボタンの値が変わったときに実行される処理を設定。オブジェクトに SwapLightmap を割り当て、関数 Corevale_SwapLightmap > SwapLightmapData() を選択。

動作テスト

テスト用にmetallic の値を 1 に設定したマテリアルを割り当てた Sphere オブジェクトをシーンに配置して再生。トグルボタンを切り替えるとライトマップとリフレクションプローブのキューブマップが切り替わりました!(画像クリックで拡大)

WebGLでビルド

動作確認したシーンにライトプローブの切り換えが確認できるようにプレイヤーキャラクター Robot Kyle を配置。リフレクションプローブの切り換えが分かりやすいように Capsule オブジェクトを頭に追加してみました。

以前の記事 プレイヤーキャラクターをマウスクリックした位置に移動させる の内容と同じ方法を使用してマウスクリックで操作できるようにしました。
画像クリックで再生(ファイルサイズ:約18MB)

参考記事

今回の記事はこちらのWebサイトの記事を参考にしました。感謝!
【Unity】モバイル向けのライトマップTipsと、ライトマップを動的に更新するHack – テラシュールブログ

Unity 5はリアルタイムな光源を基本としている節がありますが、モバイル上では依然としてパフォーマンスを稼ぐためライトマップをベイクする方が良いです。 今回はそのライトマップの色々なアプローチについて紹介します。 ライトを焼く ライトマップを焼く時間を短縮する リアルタイムGIをOFFに 重要度の低いライトマップの解...

How to create lightmap for day and for night and switch them in runtime. – Unity Forum