こんにちは、Unityエンジニアのオオバです。

お悩みさん
お悩みさん
  • Unity実行までの時間がかかるようになった
  • もっと短時間で結果を確認したい
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    Unityでゲーム開発していると、途中からどんどん動作が重くなります。

    など。さまざまな待機時間が増えてきます。

    そこで本記事ではUnityエディタの 再生モードまでの待機時間を「爆速化」 する設定を紹介していきます。

    お悩みさん
    お悩みさん
    ちょっと大げさじゃない?

    大げさに聞こえるかもしれませんが、本当に爆速化します。オオバはUnityを使い始めて12年経ちますが、この設定を初めて使用したとき 「実行までが早すぎる!!!」 と衝撃が走るくらい感動しました。

    皆さんにもオオバと同じ感動を味わっていただきたいので、最後までぜひ読んでみてください。

    Enter Play Mode Settingsを設定しよう

    はじめに結論を言うと、Unityを爆速化させる設定は Enter Play Mode Settings です。Enter Play Mode Settingsを設定するしないでUnityは 別次元 の環境になります。

    読むより見た方がわかりやすいと思うので、次の動画ポストを確認してみてください。

    Unityエディタ再生ボタンを押してから計測したゲーム実行までの時間です。通常8秒かかっていたところ、Enter Play Mode SettingsをONにしたことで2秒へ 75%高速化!!

    もちろんUnityプロジェクト内の状況、使用するパソコンによって結果は変わってきますが、Unityエディタの実行までの時間が圧倒的に高速化します。

    そんなEnter Play Mode Settingsを皆さんにも知ってもらいたいので、分かりやすく解説していこうと思います。また良いことづくしのEnter Play Mode Settingsも大きめなデメリットと注意点があるため、ぜひ最後まで読んで確認してみてください。

    👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

    Unityエディタの再生モードまでの時間とは?

    今回紹介するUnityエディタ高速化は 「Unityエディタの再生モードになるまでの時間」 です。

    【Unity】EnterPlayModeでUnityエディタを爆速化しよう_0

    皆さんUnityでゲーム開発する際に再生ボタンをクリックしますよね。再生ボタンをクリックしたらゲームが開始し、実装内容が正しいのか確認すると思います。

    「Unityエディタの再生モードになるまでの時間」とは
    再生ボタンをクリックしてからゲームが開始するまでの時間 です。

    お悩みさん
    お悩みさん
    再生までの時間が早くなったところで効果はあるの?
    オオバ
    オオバ
    めちゃくちゃ効果があります

    開発序盤はそこまで効果は感じないかもしれませんが、 中盤後半、リリース後の運用時になるほど効果が大きく現れます。

    なぜなら開発が進むにつれてアセット数がどんどん増えていくからです。特にソースコードが増えると初期化処理に時間がかかり再生モードまでの時間が伸びていきます。

    しかも 再生ボタンって1日に何度もクリックしませんか?

    何度も実行する処理を高速化することで開発時間全体の短縮に繋がります。 以降の章で紹介するEnter Play Mode Settingsをぜひ検討してみてください。

    Enter Play Mode SettingsがUnityエディタを高速化させる理由

    Enter Play Mode Settingsの適用がなぜUnityエディタが高速化するのか理由を知ることでより納得できると思います。

    なぜEnter Play Mode SettingsがUnityエディタを高速化するのか?

    理由は いろんな処理を スキップ しているから です。ざっくり解説すると次のような Unityエディタの内部処理をスキップ しています。

    詳しくは公式ドキュメントでご確認ください。

    Enter Play Mode Settingsの有効化によるさまざまな処理のスキップの結果、 Unityエディタの再生モードまでの大幅時短 を実現しているのです。

    具体的なEnter Play Mode Settingsの3種類の設定

    Enter Play Mode SettingsがUnityエディタを高速化する理由がわかったところで具体的な設定方法について解説していきます。

    【Unity】EnterPlayModeでUnityエディタを爆速化しよう_1

    Enter Play Mode Settingsは メニューEdit -> Project Settings -> EditorEnter Play Mode Settings の「When entering Play Mode」のプルダウンから設定します。

    ご覧の通りEnter Play Mode Settingsは設定なし( Reload Domain and Scene )を除くと3種類です。それぞれ内容や性質が異なるため以降の解説をぜひ読んでみてください。

    具体的なEnter Play Mode Settingsの3種類の設定

    ①Reload Scene Only

    ②Reload Domain Only

    ③Do not reload Domain or Scene

    1.Reload Scene Only

    最初のEnter Play Mode Settings設定は 「Reload Scene Only」 です。Reload Scene OnlyはUnity実行時にシーンだけを初期化するようになります。つまり C#スクリプト初期化ない設定 です。

    C#スクリプトを初期化しないため、static変数の値が初期化されません。つまり前の 再生結果を維持してしまう のです。

    static変数が初期化しないため不具合に繋がります。そこで自前でstatic変数を初期化する必要が出てきます。

    詳しくはこちらの章「→ Enter Play Mode Settingsがもたらすデメリット」で登場するのでぜひ確認してみてください。

    2.Reload Domain Only

    次の設定は 「Reload Domain Only」 です。C#スクリプトのみ初期化する設定です。つまりシーンの状態が維持されるモードです。

    Unityは再生時に新規でシーンファイルをロードします。 シーンが複雑化すればするほど待機時間が増えていく のです。つまり「Reload Domain Only」を設定するとシーンが維持されるため、待機時間が少なくなります。

    お悩みさん
    お悩みさん
    Reload Domain Onlyも何かで副作用はあるの?

    「Reload Scene Only」をONにすると static変数の初期化が必要 という副作用がありましたが、「Reload Domain Only」では特にデメリットはありません。ただただ高速化するだけなので、ほぼリスクなくUnityエディタが高速化します。

    ただし「Reload Scene Only」より高速化しづらい印象です。

    ExecuteInEditMode・ExecuteAlways使用時は要注意

    Reload Domain Onlyの唯一の副作用は「ExecuteInEditMode」と「ExecuteAlways」使用時です。

    「ExecuteInEditMode」「ExecuteAlways」とはEditモード中でもスクリプトを動作させるとはアトリビュートです。

    副作用とは何かというと再生モード時に 「Awake」が呼ばれなくなること です。次のコードを使ってUnityを実行してみてください。

    using UnityEngine;  
    
    [ExecuteAlways]  
    public class ExecuteAlwaysTest : MonoBehaviour  
    {
        void Awake() => Debug.Log("Awake() called");  
    
        void OnEnable() => Debug.Log("OnEnable() called");  
    }
    

    すると、Awakeログが表示されなくなります。
    【Unity】EnterPlayModeでUnityエディタを爆速化しよう_2

    つまり AwakeがUnityから呼ばれなくなった ということです。

    Reload Sceneを無効化した際は、ExecuteInEditMode、ExecuteAlwaysには注意しましょう。Awakeが呼ばれなくなります。

    3.Do not reload Domain or Scene

    最後のEnter Play Mode Settings設定は最も効果の高い 「Do not reload Domain or Scene」 です。

    C#スクリプトの初期化、シーンの初期化をともに行わない設定 です。C#スクリプトの初期化を行わないため static変数の初期化が必要 になります。「→ static変数を自前で初期化する方法」で詳しく解説しているので確認してみてください。

    設定オオバの感想
    Reload Domain and Scene遅い(デフォルト)
    Reload Domain Only高速
    Reload Scene Onlyそこそこ
    Do not reload Domain or Scene爆速

    Enter Play Mode Settingsの各設定をまとめるとこんな感じです。

    前述の通りEnter Play Mode Settingsの中で 「Do not reload Domain or Scene」 が最もUnityエディタを高速化するため、可能な限り設定することをオススメします。

    Enter Play Mode Settingsがもたらすデメリット

    ここからが本記事で最も重要な内容になります。Unityエディタの高速化は喜ばしいのですが、落とし穴が用意されています。

    すでに何度か登場していますが、

    「自前でstatic変数の初期化が必要」

    ということです。

    static変数とはインスタンス変数とは 全くの別物 。インスタンス変数はインスタンスが削除されればメモリからも破棄されますが、static変数はインスタンスと紐づいているわけではないため、定義するとメモリに残り続けます。

    今まではUnityエディタ側でstatic変数を初期化してくれていましたが、もしEnter Play Mode Settingsと共に生きることを決めたあなたは 自分でstatic変数の初期化する必要が出てくる ことを覚悟してください。

    お悩みさん
    お悩みさん
    static変数の初期化って難しそう...

    「static変数の初期化」と聞くと難しそうに感じますが めちゃくちゃ簡単 です。

    例えば次のようなstatic変数を使ったコンポーネントを用意しました。

    using UnityEngine;  
    public class Sample : MonoBehaviour  
    {
        // static変数  
        private static int uniqueId = 0;  
    
        void Update()  
        {
            uniqueId ++;  
            Debug.Log(uniqueId);  
        }
    }
    

    static変数「uniqueId」がUpdateで毎フレーム加算され、Consoleウィンドウに数値が出力されるサンプルです。

    試しにPlayモードとEditモードを繰り返してみましょう。

    1回目の再生

    【Unity】EnterPlayModeでUnityエディタを爆速化しよう_3
    1から始まるため、想定通り。

    2回目の再生

    【Unity】EnterPlayModeでUnityエディタを爆速化しよう_4
    なぜか158から始まる想定外の挙動へ。

    上手の通り2回目以降の再生モードで事件が起きます。「uniqueId」の値が初期値の「1」ではなくなるのです。つまりモード切替中もstatic変数の値が維持されたまま加算されていくのです。本来起き得ない状態になるため 不具合の温床 になります。

    そこで自前でstatic変数を初期化して回避します。

    static変数を自前で初期化する方法

    Enter Play Mode Settings時代ではstatic変数の値がずっと維持されてしまうため初期化が必要だということを紹介しました。そこで 具体的なstatic変数の初期化方法 について解説していきます。

    早速コードから見てみましょう。

    using UnityEngine;  
    public class Sample : MonoBehaviour  
    {
        // static変数を初期化する処理  
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]  
        private static void Clear()  
        {
            uniqueId = 0;  
        }
    
        private static int uniqueId = 0;  
    
        void Update()  
        {
            uniqueId ++;  
            Debug.Log(uniqueId);  
        }
    }
    

    前章「→ Enter Play Mode Settingsがもたらすデメリット」で紹介したソースコードにstatic変数を初期化する処理を追加しました。重要なのは、次の4行です。

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]  
    private static void Clear()  
    {
        uniqueId = 0;  
    }
    

    「RuntimeInitializeOnLoadMethod」 アトリビュートを設定することでClear関数はUnityエディタ再生モード直後に実行するようになります。つまり、Clear関数内にstatic変数を初期化する処理を記述すれば良いということです。

    今回の場合はstatic変数「uniqueId」に「0」を代入することがstatic変数の初期化でした。オブジェクトならnullを、構造体ならdefaultを代入するといったケースもあると思います。使用する変数の型によって切り替えていきましょう。

    今回のサンプルは「Clear」という関数名にしましたが、自由に決めてもらって大丈夫です。

    RuntimeInitializeOnLoadMethodにはいくつか種類がある

    今回登場した 「RuntimeInitializeOnLoadMethod」 について少し補足します。「RuntimeInitializeOnLoadMethod」はUnityが提供するアトリビュート(属性)で、設定したstatic関数を再生モード直後に呼び出す重要な機能です。

    また「RuntimeInitializeOnLoadMethod」にはいくつか種類があり、実行タイミングが異なります。

    実行順(小さい順から実行)種類実行タイミング
    1BeforeSplashScreen_スプラッシュスクリーンが表示される前(最初のシーンはまだロードされていない)
    2SubsystemRegistrationランタイムの起動時、最初のシーンがロードされる前
    3AfterAssembliesLoadedすべてのアセンブリがロードされ、プリロードアセットが初期化された後(最初のシーンはまだロードされていない)
    4BeforeSceneLoad最初のシーンのオブジェクトがメモリにロードされるが、Awake() の前
    5AfterSceneLoad最初のシーンのオブジェクトがメモリにロードされ、Awake() が呼ばれた後

    この中で本記事で紹介しているEnter Play Mode Settingsのstatic変数の初期化は SubsystemRegistration を使用します。Unity公式サンプルでも同様に紹介されているので確認してみてください。

    余談ですが RuntimeInitializeOnLoadMethod はコンポーネント無しで処理を実行できる便利機能なので、覚えておいて損はありません。ゲーム実行したら最初に必ず呼びたい処理などで活用できます。

    外部アセット導入時には注意が必要

    「→ Enter Play Mode Settingsがもたらすデメリット」に関わる内容ですが、あなたのUnityプロジェクトに外部アセットが導入されている場合は注意が必要です。

    アセットによってはstatic変数が初期化されていない場合もあるからです。

    こういった症状の場合はEnter Play Mode Settingsが怪しいです。static変数の不具合の可能性があります。

    ソースコードが提供されていて書き換えられるなら「→ static変数を自前で初期化する方法」を参考に処理を変更しましょう。

    上記のようなケースなら速度は落ちますが「Reload Domain Only」を設定するのも手です。「Reload Domain Only」ならstatic変数はUnityエディタ側で初期化するため不具合が直るかもしれません。

    それでも継続して不具合が起きるなら、Enter Play Mode SettingsをOFFにするのも1つの手です。

    ゲーム開発が前進しないことが最も時間の無駄ですからね。

    Unity爆速化設定Enter Play Mode Settingsまとめ

    本記事ではUnityエディタの実行までを爆速化させる設定「Enter Play Mode Settings」について解説してきました。

    簡単に記事の内容をまとめます。

    Unity爆速化設定Enter Play Mode Settingsまとめ

    ①Enter Play Mode SettingsでUnityの実行が爆速化

    ②3種類の設定がある

    ③最も高速化するのは「Do not reload Domain or Scene」

    ④static変数の初期化を忘れずに

    ⑤外部アセット使用時は気を付けて

    こんな感じです。

    オオバはUnityエディタにEnter Play Mode Settingsがリリースされてから 必ず導入 するようにしています。なぜなら開発効率が爆上がりするからです。

    Unityゲーム開発中で最も無駄な時間の1つは 再生モードまでの待機時間 だと思っています。再生モードはUnityで開発する上で1日に何度も実行する作業であり、この回数によってゲームのクオリティに差がつくと言っても過言ではありません。

    再生モードの回数を稼ぐためには、再生モードまでの時短しかありません。つまりEnter Play Mode Settingsが必須設定なのです。Enter Play Mode Settingsを導入してから 1日にできる作業量が増えた 実感があります。

    もしまだEnter Play Mode Settingsを導入していない方はぜひ一度軽い気持ちで設定してみてください。

    注意点は一度設定すると快感すぎて元に戻れないということです。オオバがまさにそうです。

    それくらい Enter Play Mode SettingsはUnityエディタの必須設定 ということがこの記事で伝わってくれたら嬉しいなと。

    この記事があなたのゲーム開発のお役に立ったら幸いです。

    Unityオブジェクトの描画順の制御って難しいですよね。
    この度、Unityの描画順を体系的に学べる「Unity描画順の教科書」を執筆しました。

    Unityの描画順を基礎から学びたい方はぜひ確認してみてください!
    Unity描画順の教科書

    最後まで読んでいただきありがとうございました!
    すばらしい効率的なゲーム開発ライフをお過ごしください。

    オススメ記事
    検証環境