Unity を検索

Unity 2019.3 で再生モードへの素早い切り替えが可能に

2019年11月5日 カテゴリ: Engine & platform | 5 分 で読めます
シェア

Is this article helpful for you?

Thank you for your feedback!

再生モードは、Unity での作業を快適なものにするための基本的な要素です。しかし、プロジェクトが複雑になってくると、再生モードの起動に時間がかかることがあります。再生モードの開始・終了の切り替えが素早くなればなるほど、修正作業やそのテストのスピードもアップします。このため、Unity 2019.3 ベータ版で、Configurable Enter Play Mode を実験版機能として公開します。

現段階では、エディターで再生モードに入ると Unity は 2 つの事を実行します ― スクリプトの状態のリセット(Domain Reload)と、シーンの再ロード(Scene Reload)です。これには時間がかかり、プロジェクトが複雑になればなるほど、新しく加えた変更を再生モードでテストする際の待機時間が長くなります。しかし Unity 2019.3 ベータ版からは、この「Domain Reload」と「Scene Reload」の 2 つのアクションのどちらかまたは両方を無効にすることが可能になります。

社内テストの結果、これにより待機時間が(プロジェクトによって)最大で 50% ~ 90% 短縮されることが分かっています。

某 AA 作品、Unity の『FPS Sample』、『Megacity』、そして空のプロジェクトを使って、Configurable Enter Play Mode のテストを行いました。上のグラフは、エディターが再生モードを起動するのに掛かった秒数を表しています。数字が小さいほど好ましい結果となります。

Edit > Project Settings > Editor から「Enter Play Mode Options」をオンにすると、 「Reload Domain」と「Reload Scene」のオプションが利用可能になります。詳細は Unity ドキュメンテーションの、再生モードの設定方法に関するセクションをご参照ください。

このオプションを使用すると、コードに変更が加えられていない場合に Enter Play Mode の処理から「スクリプトの状態のリセット(Domain Reload)」と「シーンの再ロード(Scene Reload)」の片方あるいは両方を省くことができます。また、再生モードを開始する前にゲームの状態をリセットしたい場合は、API とコールバックによって本機能にアクセスすることも可能です。

下の図は「Reload Domain」と「Reload Scene」をオフにしていない場合(Before)とオフにした場合(After)それぞれの、Enter Play Mode の処理を示すものです。

Unity が再生モードに入る時に実行する処理に関する詳細はドキュメンテーションでご確認いただけます。

本機能は現段階では試験的なものであり、全ての Unity パッケージが Domain Reload と Scene Reload の無効化に対応済み(検証済み)なわけではありません。何か問題を発見された場合は、フォーラムからご報告くださいますようお願いいたします。

Domain Reload をオフにした場合にスクリプトを正しく修正する方法

上述の通り、Domain Reload の回避は非常に簡単に行えますが、これには代償が伴います。再生モードの開始時にスクリプトの状態が正常にリセットされるようにするために、スクリプト内で static フィールドと static イベントハンドラーを調整することが必要になります。

以下のサンプルコードには、プレイヤーがジャンプボタンを押した時に上昇するカウンターが含まれています。「Reload Domain」がオンになっている場合、再生モードの開始時にカウンターが自動的にゼロにリセットされます。「Reload Domain」をオフにすると、カウンターがリセットされずに、再生モードの開始時・終了時に値が保持されるようになります。つまり、エディターでプロジェクトを実行した時に、(前回の実行時に値が変更されていれば)カウンターがゼロではなくなっている可能性が出てくるということです。


public class StaticCounterExample : MonoBehaviour
{
    // Domain Reloading が無効の場合、このカウンターはゼロリセットされない
    static int counter = 0;

    // 1 フレームに 1 回 Update が呼び出される
    void Update()
    {
    	if (Input.GetButtonDown("Jump"))
    	{
            counter++;
            Debug.Log("Counter: " + counter);
        }
    }
}

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] 属性を使用して、Domain Reload をオフにした場合にカウンターが正常にリセットされるように値を明示的にリセットしてください。以下に一例を示します。


using UnityEngine;

public class StaticCounterExampleFixed : MonoBehaviour
{
    static int counter = 0;

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    static void Init()
    {
    	Debug.Log("Counter reset.");
    	counter = 0;
    }

    // 1 フレームに 1 回 Update が呼び出される
    void Update()
    {
    	if (Input.GetButtonDown("Jump"))
    	{
            counter++;
            Debug.Log("Counter: " + counter);
    	}
    }
}

Domain Reload をオフにすると、再生モードの終了時に、メソッドが静的なイベントハンドラーから登録解除されなくなります。静的なイベントハンドラーでメソッドを登録するコードがある場合は、これにより問題が発生する可能性があります。例えば、エディターでプロジェクトを初めて再生するとメソッドが通常通り登録されます。しかしこれを再び再生した時に、これらのメソッドは(1 回目の時に加えて)もう 1 回登録されることになり、したがってイベントの発生時に重複して呼び出されることになります。

以下のコードは静的なイベントハンドラー Application.quitting にメソッドを登録します。


using UnityEngine;

public class StaticEventExample : MonoBehaviour
{
    void Start()
    {
    	Debug.Log("Registering quit function");
    	Application.quitting += Quit;
    }

    static void Quit()
    {
    	Debug.Log("Quitting!");
    }
}

上のサンプルコードは、Domain Reload がオフになっていると、再生モードが開始される度に新しく「Quit」メソッドを追加します。その結果、再生モードが終了される度に「Quitting!」のメッセージの表示が 1 回ずつ増えていくことになります。

[RuntimeInitializeOnLoadMethod] 属性を使用して明示的にメソッドを登録解除し、重複して追加されないようにしてください。


using UnityEngine;

public class StaticEventExampleFixed : MonoBehaviour
{
    [RuntimeInitializeOnLoadMethod]
    static void RunOnStart()
    {
    	Debug.Log("Unregistering quit function");
    	Application.quitting -= Quit;
    }

    void Start()
    {
    	Debug.Log("Registering quit function");
    	Application.quitting += Quit;
    }

    static void Quit()
    {
    	Debug.Log("Quitting the Player");
    }
}

Domain Reload をオフにした場合にスクリプトが正常に実行されるようにするための修正に関する詳細は、ドキュメンテーションをご参照ください。

アセットストア

Unity では、アセットストアで人気のパッケージを確実に Domain Reload・Scene Reload の無効化に対応させたいと考えています。ご自分のプロジェクトで問題が発生したら、該当パッケージのパブリッシャー様にご報告いただくという形でご協力いただければありがたく思います。

Unity 2019.3 ベータプログラムにご参加ください

現在、ご自分のプロジェクトで再生モードの開始に時間がかかる場合は、本機能によって大幅なスピードアップが望めるでしょう。 ぜひ Unity 2019.3 ベータプログラムにご参加の上、本機能をお試しください。皆様のご意見・ご感想をフォーラムでお待ちしております。本機能は現段階では実験版です。皆様のニーズに合った機能の実現に向けて、ぜひご協力ください。特に(あらゆる種類の)問題についてのご報告をお待ちしております。

すでに本機能をお試しになり、コミュニティ全体にとって為になる貴重なご意見をお寄せくださったフォーラムユーザーの @Sini さん、@chrisk さん、@Peter77 さん、@Baste さんに深く感謝申し上げます。ありがとうございました。

2019年11月5日 カテゴリ: Engine & platform | 5 分 で読めます

Is this article helpful for you?

Thank you for your feedback!