Table of Contents
Unityで複数のシーンを利用するアプリを作成した際、他のシーンに比べて顕著に読み込みが遅いシーンがあった場合に確認するとよいであろう点を個人的な体験から紹介します。
Assetの読み込み方式やサイズを変更する
Unityで読み込みに時間がかかる場合、大抵問題となっているのはシーンで読み込む画像や音声などのAssetファイルであることが多いです。
まず、これらから余計なものを読み込む設定が含まれていないかどうか確認します。必要なファイルだけになったら、ファイルごとの読み込み方式などをチェックしましょう。
ちなみに、全く使用(参照)されないアセットはビルド時にUnityが自動的に含まれないようにしてくれますので、わざわざ削除する必要はありません。
音声ファイルの例
例えば、音楽など比較的容量の大きな音声ファイルは”Load Type“を適切なものにしなければ余計なロード時間が発生してしまいます。シーンを読み込む直前で数分の音楽を一度に読み込もうとすれば、数秒アプリが操作できない時間ができてしまうかも知れません。
長い音楽などは”Load Type”を Streaming にしたり、”Load In Background“のオプションを活用すると良いでしょう。
画像ファイルの例
スプライトやUIなどに使用する画像ファイル(テクスチャ)は、余計な大きさのものを読み込もうとするとロスタイムが生じるかも知れません。
Unityには元のファイルを変更せず、読み込む画像サイズのみを変更する仕組みがあります。
テクスチャのインスペクターを開き、”Max Size“を変更して必要最低限の大きさに調節してみましょう。
元ファイルは変更されていませんが、Unity内においてサイズが削減されます。
シーン自体が肥大化・Awakeの多用
大量のオブジェクトを初めから配置したシーンは当然、読み込みに時間がかかります。
開始時点に画面に映らないオブジェクトは、カメラが近付いてから生成されたりアクティブに切り替わるように設定を見直してみましょう。
シーン内のオブジェクトにアタッチされているスクリプトにAwakeメソッドがある場合、シーン読み込みと同時に実行されます。
そこで時間のかかる処理を行っていたり、時間がかかる処理でなくても大量のオブジェクトからAwakeが実行される状況であったりすると、開始時のロードによって一瞬フリーズしてしまう原因となります。
プロジェクト設定の見直し
プロジェクト全体の設定(Project Settings)には、グラフィックや物理挙動、アプリのクオリティなどの項目があります。必要以上に高品質な設定になっていないか確かめてみましょう。
シーンの読み込みは非同期(Async)を使う
シーン管理クラス(SceneManager)にある読み込みメソッドには SceneManager.LoadScene と SceneManager.LoadSceneAsync があります。
前者はシーンを読み込んでいる間は完全に画面が停止し、入力も受け付けなくなってしまうため、ユーザーはアプリがフリーズしたと誤解してしまう恐れがあります。単純に反応が悪いとストレスを与えてしまうことにもなりかねません。
従って、後者の LoadSceneAsync を使って、読み込み時間にシーンをロードしていることを知らせるインジケータを表示すると良いでしょう。シーンロードの時間には直接影響しませんが、利用者にとって親切な設計になると思います。
以下のコードは LoadSceneAsync によってシーンを読み込んでいる間にインジケータをアニメーションさせる例です。
public void GoToMenu() { indicator.SetActive(true); StartCoroutine(LoadSceneAsync()); } IEnumerator LoadSceneAsync() { AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(menuSceneName); while (!asyncLoad.isDone) { // シーンの読み込みが終わるまでインジケータを表示し回転させる indicator.transform.Rotate(Vector3.back, 2); yield return null; } }
また AsyncOperation のプロパティである allowSceneActivation を false に設定することで、シーンを90%読み込んだ段階で待機させることができます。その後、シーンが必要な時に true に切り替えるとロードが行われます。
シーン読み込みの進捗率は progress で確認できます。
IEnumerator LoadSceneAsync() { AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName); asyncLoad.allowSceneActivation = false; while (!asyncLoad.isDone) { // シーンの読み込みが90%以上だったらスペースキーでロード if (asyncLoad.progress >= 0.9f) { if (Input.GetKeyDown(KeyCode.Space)) { asyncLoad.allowSceneActivation = true; } } yield return null; } }
その他の最適化など
以下の記事にも、実際にゲーム制作を行う中で経験したゲーム実行時の速度低下とその対処法などについて記載しました。
シーンの読み込み速度に関わる最適化についても書いていますので、よろしければご覧いただければと思います。