Photon Fusion for Unityで特定のシーンをデバッグしやすくする手法

# はじめに

開発が進んでくるとシーンが増えていき、任意のシーンへの正常な遷移フローが長くなっていきます。そのため、任意のシーンで実装・テストする際のイテレーションの時間コストが高なってしまいます。

特定のシーンを直接起動出来るようにする方法が一般的で、Unity社とPhoton Fusionを提供するExitGames社の2社が共同開発したBR200というサンプルプロジェクトもこの方法を採用しています。

本記事ではBR200を参考に、特定のシーンを手早くデバッグするための2つの手法についてと、Photon Fusionを採用している場合の注意点について紹介します。

### 前提記事

Photon Fusionの基本的な解説は別記事で行っています。詳しく知りたい方は以下のリンクからご参照下さい。

[Photon Fusion for Unityの導入手順とPUN2との機能比較](https://qiita.com/nimushiki/items/d6fe4f0cbe0437677fa8)

BR200は、Unity社とPhoton Fusionを提供するExitGames社の2社が共同開発した、200人同時参加可能なバトルロイヤルゲームの完成サンプルプロジェクトです。

BR200について知りたい場合、実装例を詳しく知りたい場合は、BR200の紹介記事がありますのでそちらを御覧ください。

[Photon Fusion for Unityの公式サンプルBR200を触ってみた　基礎編](https://qiita.com/nimushiki/items/dde8614c8173cd6537e0)

関連記事

[https://qiita.com/tags/photonfusion](https://qiita.com/tags/photonfusion)

### 動作確認環境

Windows 10 Home 21H2

Unity 2021.3.5f1

BR200 Version 1.0.1

# BR200を試すための事前準備

BR200は無料ダウンロード可能かつ実行も可能なプロジェクトです。最低限実行するだけであれば以下の準備をすれば可能です。

- Unity 2021.3.5f1　以降を使用
- 空プロジェクトを作成、UnityAssetStoreからBR200をインポートする
- Photonの公式サイトでの登録作業
    - 会員登録をしておく
    - ダッシュボードからBR200用のAppIDを取得して設定する

# 任意のシーンから開始する

これはそのままの意味ですが、どのシーンからでも直接ゲームを起動できるようにする方法で、Unityの入門書や記事でも紹介されていたりします。ゲームの正式な手順を踏まないため、以下のような特徴があります。

- メリット
    - 起動が早い
    - わかりやすい
    - 初期化が必要ない場合、実装も簡単
- デメリット
    - Photon Fusionを使用している場合など、初期化用の処理を作る必要が出てくる可能性が高い
    - 他のシーンでバグが発生しやすい

この手法で一番問題になりやすいのが、他シーンでバグが出やすいことです。

他のシーンを開かずに実装を進める時間が長くなるため、見ていない箇所への副作用を見逃してしまう可能性が高くなります。

この問題を起こさないためには、定期的に正式な手順を踏んで実行するか、後述するもう一つの手法に変えるとよいでしょう。

## BR200での実装

正確には任意のシーンではなく任意のゲームモードから起動するサンプルになりますが、公式サンプルプロジェクトであるBR200の実装を見てみます。

TemplateシーンにあるStandaloneManagerで設定をしておくと、それに応じたモードが起動します。起動すると以下のような流れで処理が行われます。

- StandaloneManager.cs
    
    起動時にPhotonに接続してるか確認する
    
    接続してなかったら、_defaultConfigurationに設定された値をNetworking.csに渡す
    
- Networking.cs
    
    Global.csでstatic化してUpdateで設定を常時監視
    
    StandaloneManager.csから設定を受け取ったら処理開始
    
    ConnectPeerCoroutineの中で非同期処理
    
    runner.StartGame
    
    NetworkGame.csのActivateでプレイヤーをRunner.Spawnする

### Photon Fusion利用時の注意
Photon Fusionを採用しており、Runner.StartGameとRunner.Spawnなどの接続処理が複数シーンで必要になる場合、を各シーンにそれぞれに実装してしまうとバグの温床になってしまいます。初期化処理の一つとして共通化するとよいでしょう。

BR200では、設定の変更をトリガーにシーンの読み込み～接続～プレイヤーのスポーンを行っています。主にNetworking.csがその処理を担っており、正式な手順の場合と直接起動の場合で処理が共通化されています。違うのは設定を反映するタイミングです。

# 任意のシーンまで自動操作をする

こちらの方法は通常プレイと同じ手順を自動・高速で通すことで、任意のシーンを早く表示するという目的を達成します。正常系を通して起動するため、以下のようなメリットデメリットがあります。

- メリット
    - 他のシーンへの影響がでた場合に知覚しやすく、バグを見つけやすい
- デメリット
    - 直接起動より実行に時間がかかる
    - 人間よりはるかに早い操作が可能になるため、タイミングに注意が必要

実装の方針としては、自動実行用のオブジェクトでシーンの状態を監視し任意のイベントを発火していく、といった自動操作用のオブジェクトを用意します。

```AutoStart.cs
public class AutoStart : MonoBehaviour
    {
        [SerializeField]
        private bool MenuSceneLoaded;
        [SerializeField]
        private bool PlayButtonPushed;

        void Awake()
        {
            DontDestroyOnLoad(gameObject);
        }

        void Update()
        {
            while (MenuSceneLoaded == false) {
                if (SceneManager.GetActiveScene() == null) continue;
                if (SceneManager.GetActiveScene().name == "Menu") { 
                    MenuSceneLoaded = true; 
                    GameObject.Find("PlayButton").GetComponent<UIButton>().onClick.Invoke();
                }
            };
        }
    }
```

このサンプルコードは、BR200のLoaderシーンに設置して置くことで起動時に自動でキャラ選択を行うというものですが、以下のようなポイントがあります。

シーンをまたぐ必要があるため、DontDestroyOnLoadにしておきます。専用のシーンを用意しても良いですが、その場合は通常のシーン読み込み（SceneManager.LoadScene、オプションはLoadSceneMode.Single）をすると、読み込もうとしたシーン以外は破棄されてしまうので注意が必要です。

人間よりも遥かに速い操作が可能なため、適切なウェイト処理を入れて問題がないようにする必要があります。

通常マウスやタッチで行うボタン操作は、onClick.Invokeを呼ぶことで実現可能です。

操作の途中に設定項目や選択肢がある場合、任意の値を指定できるように[SerializeField]や設定ファイルを用意すると良いでしょう。

## BR200での動作例

Loaderシーンを実行をした場合、上記の設定を行う前後での動作を比較してみます。

こちらが通常の実装での動作です。

![自動操作なし](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/59acb2e2-d8ff-698d-1d40-f893125cc45c.gif)

こちらが先程のサンプルコードを実装した場合の動作です。1画面目のキャラクター選択画面がマウス操作なく一瞬でスキップされているのがわかると思います。

![自動操作あり](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/46ab44b4-226d-f3a1-5e8b-b576a8e25acc.gif)

# まとめ

任意のシーンを素早く開始できればその分だけ待ち時間が減り、実装完了までにかかる時間を短縮することができます。しかし、今回紹介したどちらの方法にしても通常の実装へ大きな影響があります。

最初期においてはそもそもシーンが少なく実装のコストに対してメリットが少ないため、ある程度実装が進み方針が決まってきた段階で実装を検討するとよいでしょう。