シーンローディング
概要
FusionにはUnityのシーンを処理する実装は含まれていませんが、INetworkSceneManager
インターフェースによって、様々なシーン関連のイベント(シーン遷移など)にどのように反応するかを定義できます。INetworkSceneManager
の実装は、NetworkRunner
に渡した後にSceneManager
とみなされます。
INetworkSceneManager
の実装は、NetworkRunner.StartGame()
のStartGameArgs.SceneManager
で渡す必要があります。実装が渡されない(null)なら、FusionはNetworkSceneManagerDummy
クラスのインスタンスを作成し、シーンオブジェクトを生成できない旨のエラーログを出力します。
Fusionにはデフォルト実装のNetworkSceneManagerDefault
が用意されていて、以下のことが可能です。
- シーンのロード・アンロード
- Addressableなシーンのロードに対応
- アクティブなシーンのリロード
- 最大8つ同時でAdditiveなシーンのロード
- マルチピアモードに対応(各
NetworkRunner
に対しての、正しいPhysicsScene
の関連付け)
シーンのロード・アンロード
重要: LoadScene()
とUnloadScene()
は、サーバー/ホストまたはマスタークライアントからのみ呼び出すことができます。(これはNetworkSceneManagerDefault
によって強制されていて、独自実装でも同様に強制する必要があります)
シーンをロードするには、SceneRef
とLoadSceneParameters
を渡してNetworkRunner.LoadScene()
を呼び出します。LoadSceneMode.Single
では前のシーンは全てアンロードされますが、LoadSceneMode.Additive
では前のシーンはロードされたままになります。
C#
// Loading 3 scenes in additive mode.
if (Runner.IsSceneAuthority) {
Runner.LoadScene(SceneRef.FromIndex(1), LoadSceneMode.Additive);
Runner.LoadScene(SceneRef.FromIndex(2), LoadSceneMode.Additive);
Runner.LoadScene(SceneRef.FromIndex(3), LoadSceneMode.Additive);
}
SceneRef
のインデックスは、Unityのシーンのビルドインデックスです。現在のシーンのインデックスを取得するには、SceneManager.GetActiveScene().buildIndex
を使用します。他のシーンのインデックスは、SceneUtility.GetBuildIndexByScenePath
で見つけることができます。例えば、Assets/Scenes/GameScene.unity
に格納されているシーンのロードは、以下のようなコードになります。
C#
Runner.LoadScene(SceneRef.FromIndex(SceneUtility.GetBuildIndexByScenePath("Assets/Scenes/GameScene.unity")), LoadSceneMode.Additive);
シーンをアンロードするには、アンロードするシーンのSceneRef
を渡して、NetworkRunner.UnloadScene()
を呼び出します。
C#
// Unloading scene 1.
if (Runner.IsSceneAuthority) {
Runner.UnloadScene(SceneRef.FromIndex(1));
}
シーンのアンロードとロードを順番に行って、シーンを再ロードすることも可能です。NetworkSceneManagerDefault
のVersion
フィールドはカウンタとして動作し、シーンをロード・アンロードするたびに増加します。この値は、シーンオブジェクトのIDの登録に使用され、たとえ同じシーンを再ロードしたとしても、前のシーンと新しいシーンは差別化されます。
C#
// Reloading scene 2.
if (Runner.IsSceneAuthority) {
Runner.UnloadScene(SceneRef.FromIndex(2));
Runner.LoadScene(SceneRef.FromIndex(2), LoadSceneMode.Additive);
}
SceneRef
は、シーンのインデックスからSceneRef.FromIndex(int index)
で作成するか、主にAddressableなシーンのパスからSceneRef.FromPath(string path)
で作成します。
独自のNetwork Managerの作成
NetworkSceneInfo
ユーザーが制御するアクティブなシーン情報を表し、最大8つのアクティブなシーンの複製に対応します。独自実装を作成するための良い出発点にもなります。この構造体は、シーンローディングを適切に同期するために、NetworkRunner
によって通信されます。シーン権限者(ホスト/サーバーまたはマスタークライアント)がシーン情報を変更すると、NetworkRunner
に登録されているINetworkSceneManager
のOnSceneInfoChanged()
が呼ばれます。
INetworkSceneManager
INetworkSceneManager
の独自実装をStartGameArgs
に渡すと、シーンローディングをどのように処理するかを完全に制御できます。独自実装で、Runner.InvokeSceneLoadStart(sceneRef)
とRunner.InvokeSceneLoadDone(SceneLoadDoneArgs)
を呼ぶ必要があることに注意しましょう。デフォルトの挙動はNetworkSceneManagerDefault
の実装を確認してください。
独自のSceneManager
を実装する場合、インターフェースで以下を実装してください。
void Initialize(NetworkRunner runner)
:NetworkRunner
が初期化された時に呼ばれます。NetworkRunner
の参照を格納したり、必要な事前処理が行うために使用してください。void Shutdown()
:NetworkRunner
が停止した時に呼ばれます。参照を開放したり、保留中の処理を停止するために使用してください。bool IsBusy
:SceneManager
がシーンのロード等でビジー状態であることを、NetworkRunner
や他のシステムに知らせる必要がある場合に使用してください。Scene MainRunnerScene
:どのシーンがNetworkRunner
のメインのシーンであるかを知るために使用してください。これは主にマルチピアモードで使用されます。(詳細はデフォルト実装を確認してください)bool TryGetPhysicsScene2D(out PhysicsScene2D scene2D)
:2D物理シーンをoutパラメーターに出力し、実行結果を返します。bool TryGetPhysicsScene3D(out PhysicsScene scene3D)
:3D物理シーンをoutパラメーターに出力し、実行結果を返します。void MakeDontDestroyOnLoad(GameObject obj)
:ロード時にオブジェクトが破棄されないようにします。マルチピアモードで使用されます。(詳細はデフォルト実装を確認してください)void MoveToRunnerScene(GameObject obj)
:オブジェクトをNetworkRunner
のシーンに移動します。マルチピアモードでのみ使用されます。(詳細はデフォルト実装を確認してください)bool IsRunnerScene(Scene scene)
:シーンがNetworkRunner
のシーンかどうかを返します。マルチピアモードで使用されます。(詳細はデフォルト実装を確認してください)NetworkSceneAsyncOp LoadScene(SceneRef sceneRef, LoadSceneParameters parameters)
:新しいシーンをロードするために使用してください。シーンのロード方法は完全に開発者次第ですが、NetworkRunner.RegisterSceneObjects(SceneRef scene, NetworkObject[] objects, byte loadId = 0)
で新しくロードしたNetworkObject
を登録するステップが必要です。追加のloadId
パラメーターを渡すことで、各シーンがシーンオブジェクトのユニークIDを生成することが保証されます。NetworkSceneAsyncOp UnloadScene(SceneRef sceneRef)
:シーンをアンロードするために使用してください。void OnSceneInfoChanged()
:NetworkRunner
のINetworkSceneInfo
が変更された時に呼ばれます。クライアントでシーンローディングの反応・実行するために使用してください。SceneRef GetSceneRef(string sceneName)
:与えたシーン名のSceneRef
を返すために使用してください。