見出し画像

【unity】シーンの切り替えを雑に実装してませんか?

私は過去に作成したゲームでシーンのロードを
何も考えずに、というか何の知識もなく
SceneManager.LoadScene()だけを使ってました
今思うと、真っ暗な画面のまましばらく待たされたりとか…。

待たされるプレイヤーになんの配慮もないのは微妙ですよね
この記事ではスムーズなシーンの切り替えとロード画面の実装をします
これまで何となくシーン変更を実装していた方は参考にしてください


1. シーンの読み込み

そもそもUnityでは、シーンの読み込みには主に二つの方法があります。一つ目は同期読み込み、もう一つは非同期読み込みです。同期読み込みはシンプルで直感的ですが、大きなシーンの場合や低スペックのデバイスでは待ち時間が発生しやすくなります。
非同期読み込みでは、SceneManager.LoadSceneAsyncを使用してシーンを非同期的に読み込みます。これにより、メインスレッドをブロックせずにロード画面などの表示を行うことができます。

2.非同期読み込みのメリットとは

同期処理に比べて導入に手間が多少かかりますが
もちろんメリットがあります
私なりにまとめてみました

a. 待ち時間の最小化: 非同期読み込みを使用することで、プレイヤーに待ち時間を最小限に抑えたゲーム体験を提供することができます。同期読み込みでは、シーンの読み込みが完了するまで次の処理に進まないため、大きなシーンや低スペックのデバイスでは待ち時間が長くなりがちです。
しかし非同期読み込みでは、シーンの読み込みがバックグラウンドで行われるため、プレイヤーはロード画面や待機画面を表示しつつ、ゲームのプレイや操作を続けることができます

b. メインスレッドのブロック回避:
意外と見落としがちなポイントですが
同期読み込みでは、シーンの読み込みがメインスレッドで行われるため、
他の処理がブロックされる可能性があります。これに対して非同期読み込みでは、読み込みがバックグラウンドで行われるため、メインスレッドがブロックされることなく、ゲームの描画や操作を継続することができます
特に大規模なゲームや低スペックのデバイスでは、
この点が重要となります

c. ユーザーエクスペリエンスの向上:
プレイヤーにとって、待ち時間はストレスや不快感を引き起こす要因の一つです
非同期読み込みを使用することで、待ち時間を最小限に抑え、プレイヤーのエクスペリエンスを向上させることができます。プレイヤーは待ち時間中にロード画面や待機画面を表示しながら、ゲームの操作やプレイを続けることができるため、より没入感のあるゲーム体験を提供することが可能です

3.実際に実装してみる

①「ロードシーン」の作成:
Unityのメニューから、「File」→「New Scene」を選択して新しいシーンを作成します
このシーンには、ロード画面用のUI要素や必要なスクリプトを配置します
プログレスバーやロード中のメッセージなどが一般的です
今回はプログレスバー
「現在のシーン」から「ロードシーン」への移行:
現在のシーンに移行するトリガーとなる何らかのイベント(ボタンクリック、ゲーム開始時など)を設定します。
そのイベントを検出して、非同期読み込みを開始します。
以下は、例としてボタンクリック時に非同期読み込みを開始する方法です

using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneLoader : MonoBehaviour
{
    public void LoadNextSceneAsync()
    {
        StartCoroutine(LoadSceneAsync("LoadScene"));
    }

    IEnumerator LoadSceneAsync(string sceneName)
    {
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);

        while (!asyncLoad.isDone)
        {
            yield return null;
        }
    }
}

「ロードシーン」から「次のシーン」への移行:

  • 「ロードシーン」のスクリプトで、非同期読み込みを行います。

  • 「次のシーン」が読み込み完了したら、そのシーンへ移行します。同時に、ロードシーンもアンロードします。

using UnityEngine;
using UnityEngine.SceneManagement;

public class LoadScreenManager : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(LoadNextSceneAsync());
    }

    IEnumerator LoadNextSceneAsync()
    {
        // 前のロードシーンをアンロード
        SceneManager.UnloadSceneAsync("LoadScene");

        // 次のシーンを非同期で読み込み
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("NextScene");

        while (!asyncLoad.isDone)
        {
            yield return null;
        }
    }
}


シーンの移行処理の呼び出し:

  • 「「現在のシーン」に移行するトリガーとなるイベントを設定します。

  • そのイベントを検出して、次のシーンへの移行処理を呼び出します。

これで、「現在のシーン」から「ロードシーン」への移行、そして「ロードシーン」から「次のシーン」への移行が非同期で行われ、かつ必要なシーンが適切にアンロードされるようになります。これにより、プレイヤーは待ち時間を最小限に抑えながら、スムーズに次のシーンへ移行することができます。

アンロードって何?

アンロードとは、ゲーム開発において重要な概念の一つです。これは、ゲーム内で使用されなくなったシーンやリソースを解放することを指します。具体的には、プレイヤーが現在いないエリアや、プレイ中に不要になったゲームオブジェクト、テクスチャ、音声などのリソースをメモリから解放することを意味します。

なぜアンロードが必要なのか?

  1. メモリ効率化: アンロードすることで、不要なリソースをメモリから解放するため、ゲームが使用するメモリの量を最適化できます。特に大規模なゲームでは、メモリの効率的な管理が重要となります。

  2. パフォーマンス向上: 不要なリソースが残っていると、ゲームの処理速度が低下する可能性があります。アンロードによって不要な処理を減らし、ゲームのパフォーマンスを向上させることができます。

  3. リソースの再利用: アンロードされたリソースは再度必要になった場合でも、必要な時に再度読み込むことができます。これにより、リソースの再利用が可能となり、効率的なゲーム開発が可能となります。

  4. デバイスのリソース節約: モバイルデバイスなどのリソースが限られている環境では、アンロードによってメモリや処理能力を節約することが重要です。これにより、ゲームがより多くのデバイスで快適に動作することができます。

ただし、なんでもかんでもアンロードが必要だというわけではないです
ミニゲームなどの小規模では、シーン間の移行が比較的軽量であり、メモリの使用量が高くなりにくい場合があります。そのため、アンロードせずに全てのシーンを常にメモリに保持しておくことで、プレイヤーにシームレスなゲーム体験を提供することができます
そういった意味では非同期処理をするほどのデータ量がないゲームでは、本記事は作業量が増え、かえってプレイヤーにストレスを与えてしまうかもしれません
つまるところは「テストプレイで自分が不快に感じるほどの読み込み時間であれば対策を講じたほうが良い」といったところでしょうか
知り合いがいればプレイしてもらって感想を聞くのもいいでしょう

せっかく作ったゲームがロード一つで評価を下げないよう
工夫をするのは、重要なことですよね

おまけ 挿絵

この記事が気に入ったらサポートをしてみませんか?