【Unity】グローバルイルミネーション(GI)を使わないプロジェクトでやっておくべきこと

はじめに

こんにちは、ソーシャルゲーム事業部 ゲーム技研所属の清水です。
この記事はカヤックUnityアドベントカレンダー2018の25日目の記事になります。

最終日ですが、特に豪華というわけでもなく、パフォーマンスチューニング系のちょっとした小ネタを紹介します。

GIが不要な場合

Unityで使用可能なライティングシステムの1つに、間接光を表現できるグローバルイルミネーション(GI)があります。
Unity 5の頃に導入されたこの機能によって、Unityのライティング表現が大きく向上しました。
しかし、プロジェクトによっては不要なこともあります。
モバイル環境だとリアルタイムGIはパフォーマンスの都合で厳しいですし、フォトリアルを求めないアート表現や、ライティングを使わない2D表現のゲームではベイクしたGIも使わないでしょう。
そのような場合はGI自体を無効にしておくと、GIのための処理を省略して少しパフォーマンスを稼ぐことができます。

GIの設定箇所

GIの設定はシーンごとに保存されます。
メニューの Window > Rendering > Lighiting Settings で開ける Lighting ウィンドウの Scene タブに設定があります。(メニュー項目はUnityのバージョンによって微妙に変わります)
無効にする場合はここのチェックを外します。
f:id:shimiu:20181120110430p:plain
シーン作成時は Realtime Global IlluminationBaked Global Illumination も両方ともデフォルトで有効になっています。

Realtime の方は有効になっているだけで毎フレーム処理が走るので、不要なら必ず無効にしましょう。
古めの Android (Snapdragon 800 搭載) で Realtime GI を有効にした空っぽのシーンを再生させたところ、0.1〜1.5msくらいの振れ幅で毎フレームCPU時間を消費していることが GI プロファイラーで確認できました。

Baked の方は有効になってるだけならランタイムの負荷は変わらないようですが、staticなオブジェクトがあるとテクスチャが作られるので、不要ならやはり無効にしておいた方が良いでしょう。

新規シーン作成時にGIを自動で無効にする

プロジェクトによってはたくさんのシーンを使います。
プロジェクト全体でGIを使わない場合、すべてのシーンで個別に無効にするのは辛いものがありますし、設定漏れが出がちです。
これらの設定はスクリプトからもアクセスできるので、シーン作成時に自動で無効にする以下のようなエディタスクリプトを置いておくのがおすすめです。

using UnityEditor;
using UnityEditor.SceneManagement;

static class GIRemover
{
    [InitializeOnLoadMethod]
    static void Initialize()
    {
        EditorSceneManager.newSceneCreated += (scene, setup, mode) =>
        {
            Lightmapping.realtimeGI = false;
            Lightmapping.bakedGI = false;
        };
    }
}

Lightmapping.realtimeGILightmapping.bakedGI でそれぞれ設定できるので、シーン作成時に呼ばれる EditorSceneManager.newSceneCreated イベントに処理を登録しています。
メソッドに InitializeOnLoadMethod 属性をつけておくとスクリプトがコンパイルされたときに自動で実行されるので、その中でイベント登録をしています。

既存のシーンのGIを無効にする

すでにたくさんのシーンがあるプロジェクトで、設定を無効化していないことに後から気づくこともあります。
もちろん全シーンを一括で編集するようなエディタスクリプトを書いても良いのですが、前項のエディタスクリプトを置いておけば今後のシーンについては防げるので、既存のシーンについてはシーンファイルを雑に文字列置換することが多いです。
シーンファイルがyaml形式で保存されている前提ですが、 m_EnableRealtimeLightmaps: 1m_EnableBakedLightmaps: 1 のようにシリアライズされているので、それらを一括置換します。
シェルだと以下のようなコマンドでプロジェクト内の全シーンを置換できます。

grep -lr --include="*.unity" --null "m_EnableRealtimeLightmaps: 1" Assets/ | xargs -0 sed -i "" "s/m_EnableRealtimeLightmaps: 1/m_EnableRealtimeLightmaps: 0/g"
grep -lr --include="*.unity" --null "m_EnableBakedLightmaps: 1" Assets/ | xargs -0 sed -i "" "s/m_EnableBakedLightmaps: 1/m_EnableBakedLightmaps: 0/g"

おわりに

今年のアドベントカレンダーは本記事で終わりになります。
何か読者の方の役に立つ情報や興味を惹かれるネタがあったなら幸いです。

カヤックでは仕事でUnityを使いたいエンジニアを募集しています。
今回のアドベントカレンダーを見て何かビビッとくるものがあった方は是非ご応募ください!