スポーン(基礎)
はじめに
ネットワークオブジェクトは、通常のGameObject.Instantiate()でインスタンス化するかわりに、スポーンする必要があります。
実行時にネットワークオブジェクトをスポーンするには、Runner.Spawn()メソッドを使用します。シーンオブジェクトは、シーンがロードされた時に自動的にスポーンされるため、明示的にスポーンする必要はありません。
FusionはNetworkObjectにネットワーク間でユニークなIDを割り当てるため、すべてのクライアントはネットワークオブジェクトの各インスタンスを識別できて、それらの状態を正しく同期できるようになります。Runner.Spawn()メソッドによって、いつどのようにして新しいオブジェクトのインスタンスをネットワーク上の状態の集合に追加するかをFusionに伝えます。
重要!
ネットワークオブジェクトに対して、UnityのGameObject.Instantiate()メソッドを使用しないでください。ゲームオブジェクトはローカルでのみ生成されるため、Fusionのシミュレーションループからは完全に切り離され、ネットワーク上の状態を壊してしまいます。
Runner.Spawn
FusionのNetworkRunnerインスタンスのRunner.Spawn()メソッドは、UnityのGameObject.Instantiate()メソッドに似ています。メソッドに与えられるパラメーターは以下の通りです。
- NetworkObject型のプレハブ
- 位置(position)
- 回転(rotation)
- オブジェクトに対して入力権限を持たせたいクライアントのPlayerRef(共有モードでは使用しません)
- オブジェクトを複製する前に実行されるNetworkRunner.OnBeforeSpawned型のデリゲート
必須パラメーターはプレハブのみで、それ以外は任意のオプションです。
備考: Spawnメソッドで渡した位置と回転は、メソッドを実行したピアのオブジェクトのtransformにのみ影響します。この位置と回転を他のピアに反映させるには、NetworkTransform・NetworkTRSPを継承したコンポーネント・transformを同期する完全に独自のコンポーネントのいずれかが必要です。
C#
var obj = Runner.Spawn(prefab, Vector3.zero, Quaternion.identity, Runner.LocalPlayer, MyOnBeforeSpawnDelegate);
どのクライアントもネットワークオブジェクトをスポーンできます。ネットワークオブジェクトの状態権限は、スポーンしたクライアントに割り当てられます。
{% if Fusion_v2 %}
OnBeforeSpawned
NetworkRunner.OnBeforeSpawnedパラメーターには、シグネチャが一致するメソッドかラムダ式を渡すことができます。
C#
public delegate void OnBeforeSpawned(NetworkRunner runner, NetworkObject obj);
このデリゲートは、オブジェクトが生成された後かつ、オブジェクトがすべてのクライアント間で同期される前に呼び出されます。これによって、オブジェクトが他のシステムからアクセス可能になる前に、呼び出し側でオブジェクトに対する初期化処理を追加できるようになります。ここはネットワークプロパティの初期化に適した場所です。
C#
private void MySpawnFunction(){
    Runner.Spawn(
        _objPrefab, 
        Vector3.zero, 
        Quaternion.identity, 
        inputAuthority: null, 
        InitializeObjBeforeSpawn,
        predictionKey: null
        );
}
private void InitializeObjBeforeSpawn(NetworkRunner runner, NetworkObject obj)
{
    var objSB = obj.GetComponent<ObjSimulationBehaviour>();
    objSB.InitializeObjSettings(_currentExplosionForce);
}
多くのパラメーターを渡すことができるラムダ式を使用することも可能です。
C#
private void MySpawnFunction(){
  Runner.Spawn(
    _objPrefab,
    Vector3.zero,
    Quaternion.identity,
    inputAuthority: null,
    (Runner, NO) => NO.GetComponent<MyCustomBehaviour>().Init(myInt, myParameter)
    predictionKey: null
    );
}
Spawned
ISpawned.Spawned()は、NetworkRunnerがNetworkObjectを紐づけた(NetworkRunner.Spawn()呼び出しの結果、またはNetworkObjectを含むシーンのロード)直後に呼び出されます。Spawned()コールバックは、FusionにおけるAwake()の代替とみなすことができ、「有効な」オブジェクトが「紐付けられた」後にのみ呼び出されます。
NetworkBehaviourはISpawnedインターフェースを実装していて、Spawned()は空の仮想メソッドになっています。独自のNetworkBehaviourでSpawned()を実装するには、単にSpawned()をオーバーライドしてください。
C#
public class Example : NetworkBehaviour
{
    public override void Spawned()
    {
        // Use this instead of Start / Awake for NetworkObjects
    }
}
状態権限者がSpawned()で行うすべてのネットワークプロパティの更新は、他すべてのピア上でスポーンしたNetworkObjectインスタンスの初期値となります。しかしリモートのピアは、(関心領域、インタレストマネジメント、途中参加、優先順位などの理由で)常に状態権限者と同じティックにオブジェクトがスポーンするとは限りません。リモートのNetworkObjectが状態権限者より後のティックでスポーンした場合、そのティックに状態権限者が保持している値を初期値としてスポーンすることになります。
- 状態権限を持つピアでのスポーンは、Runner.Spawn()直後にSpawned()が呼び出されます
- 状態権限を持たないピアでは、NetworkRunnerがネットワーク上の状態を受信した際に、ローカルに存在しないNetworkObjectがスポーンします
Despawn
ネットワークオブジェクトを削除するには、オブジェクトの状態権限を持つピアでRunner.Despawn()を呼び出してください。
Despawned
Runner.Spawn()によって、NetworkBehaviourのようなISpawnedを実装したクラスでSpawned()メソッドが呼び出されるのと同じように、Despawn()によって、IDespawnedを実装したクラスでDespawned()メソッドが呼び出されます。
C#
public class Example : NetworkBehaviour
{
    public override void Despawned()
    {
        // Use this instead of Destroy for NetworkObjects
    }
}