このページは編集中です。更新が保留になっている可能性があります。

Network Object

はじめに

NetworkObjectGameObjectにネットワークIDを割り当て、ネットワーク上で共有できるようにします。すべてのプレイヤーが見ることができ、シーンの動的な部分であるGameObjectには、NetworkObjectスクリプトを設定します。

Fusionには、カスタムのネットワーク動作を派生させるための2つのNetworkObjectベースクラスがあります。

  • シミュレーション関連の動作にはSimulationBehaviour、そして
  • NetworkBehaviourは、[Networked]の状態を維持または追跡する動作のためです。

トップに戻る

NetworkObject

GameObjectのルートノードに1つのNetworkObjectスクリプトを置くだけで、階層全体を制御することができます。ランタイム時には、NetworkObjectはその階層にあるすべてのSimulationBehaviourNetworkBehaviourを検出します。

必要に応じて、NetworkObjectをネストすることができます。この場合、NetworkObjectはネストした子の中は検索せず、子のNetworkObjectにその下のすべてのSimulationBehaviourNetworkBehaviourを追跡させます。典型的な使用例としては、2人のプレイヤーが操作するシャーシと砲台からなる戦車で、ドライバーがシャーシの方向(移動)を制御し、ガンナーが砲台(射撃)を制御するというものがあります。

トップに戻る

プレハブ/オブジェクトテーブル

PrefabパラメータがFusionにとって意味のあるものであるためには(そして、すべてのクライアントがどのプレハブであるかを正確に把握するには)、プレハブ自体がFusionに登録されている必要があります。通常であれば、Fusionツールセットが自動的にプレハブを検出して登録しますが、NetworkProjectConfigを選択して、Unity InspectorのRebuild Object Tableを押すことで、手動で検出することもできます。

トップに戻る

インスタンス化/スポーン化

NetworkObjectプレハブのインスタンス化には2つのステップがあります。

  1. 編集時: クライアントの NetworkProjectConfig アセットが同一で、NetworkObject プレハブの ID が一致していることを確認します。これは NetworkProjectConfig アセットで Rebuild Object Table を実行することで行います。
  2. ランタイム では、NetworkRunnerSpawn()を、NetworkObjectプレハブをパラメータとして呼び出します。

重要: 一般的なUnityのInstantiate()メソッドを呼び出すと、壊れたローカルインスタンスが作成されてしまいます!

トップに戻る

破壊 / デスポーン

NetworkObjectを破壊するには、Runner.Despawn()を呼び出し、パラメータとしてオブジェクトを渡します。一番上のオブジェクトだけをデスポーンするには、まずネストしたオブジェクトを手動でペアレント解除する必要があります。

トップに戻る

権威

NetworkObjectには、2種類の権限(所有権)があります。

  • 入力の権限
  • 状態の権限

トップに戻る

入力と状態

入力権限では、そのオブジェクトに対するユーザーの入力を収集し、送信することができます。また、クライアントは、FixedUpdateNetwork()で同じ入力を取得して、オブジェクトの将来の状態をシミュレートしたり、ローカルに予測したりすることができます。State Authorityは、入力に基づいて状態を読み取り、シミュレートすることを可能にするため、予測と真の状態を同じコードで変異させることができます。

言い換えれば、State Authorityは、オブジェクトの状態を最終的に制御し、同期のために他のすべてのクライアントに送信されるデルタスナップショットに何を入れるかを直接指示します。最終的には、State Authorityを持つクライアントが設定した状態が、Input Authorityを持つクライアントが予測した状態を置き換えることになります。

トップに戻る

権限の割り当て

ゲームコードでは、HasInputAuthorityHasStateAuthorityプロパティを使って、クライアントが特定のNetworkObjectに対して持つ権限の種類を確認できます。

Runner.Spawn()NetworkObjectが生成されると、呼び出したクライアントは自分自身や他のクライアントに入力権限を割り当てることができます。

  • ネットワークモードがClient Authorityに設定されている場合、クライアントはオブジェクトのState Authorityを引き受けることもできます。
  • ネットワークモードが専用サーバやクライアントホストに設定されている場合は、常にState Authorityが割り当てられます。

トップに戻る

SimulationBehaviour

すべての SimulationBehaviour は、Object プロパティを使って、関連する NetworkObject にアクセスできます。

Simulation は、Fusionでネットワークの状態を更新する方法です。シミュレーションの一部であったり、シミュレーションの状態に影響を与える動作は、MonoBehaviourではなく、SimulationBehaviourから派生しなければなりません。

例えば、TanksサンプルのLevelManagerはパワーアップを産み出します。パワーアップはNetworkObjectですが、LevelManagerはシミュレーションの状態に影響を与え、それを知るだけでその動作を実行できます。したがって、SimulationBehaviourを継承するのが正しい方法です。

public class LevelManager : SimulationBehaviour
{
    [SerializeField] private float _powerupDelay;
    [SerializeField] private NetworkObject _powerupPrefab;

    private TickTimer _powerupTimer;

    public override void FixedUpdateNetwork()
    {
        // All of the level management logic happens server-side, so bail if we're not the server.
        if (!Object.HasStateAuthority) return;

        // Only active duty of the LevelManager is to spawn powerups whenever the timer expires
        if (_powerupTimer.ExpiredOrNotRunning(Runner)) {
            // Reset timer, and check if there is a free spot to spawn a new powerup
            _powerupTimer = TickTimer.CreateFromSeconds(Runner,_powerupDelay);
            SpawnPoint spawnPoint = GetSpawnPoint(SpawnPoint.Type.Powerup);

            if (spawnPoint != null) {
                Debug.Log("Spawning Powerup");
                NetworkObject powerupobj = Runner.Spawn(_powerupPrefab, spawnPoint.transform.position, spawnPoint.transform.rotation, PlayerRef.None);
                powerupobj.GetComponent<Powerup>().Init();
            } else {
                Debug.Log("Not Spawning Powerup - no free spot");
            }
        }
    }
}

動作が [Networked] プロパティへのアクセスを必要とする場合は、代わりに NetworkBehaviour を派生させる必要があります。

トップに戻る

NetworkBehaviour

NetworkBehaviourは、同じノードまたは親ノード上のNetworkObjectを必要とします。

NetworkBehaviourSimulationBehaviourであり、同期した状態を保持することができます。そのため、関連するNetworkObjectを持たなければありません。

トップに戻る

ネットワーク状態

Fusionは内部的に、現在のローカルティックのネットワーク状態を表す1つのメモリバッファを保持しています。この状態をゲームコードに公開するには、プロパティに [Networked] という属性を付けます。

ネットワーク状態の値を定義してシリアライズするには、プロパティの前に [Networked] 属性を追加します。Fusionはタグ付けされたプロパティを、独自の高性能データ・バッファとデルタ圧縮で自動的に処理します。 プロパティのセッターとゲッターはコンパイル時にカスタムコードに置き換えられ、メモリ割り当てのオーバーヘッドをなくし、最適なパフォーマンスを提供します。

public class PlayerBehaviour : NetworkedBehaviour {
  [Networked] public float Health { get; set; }
}

Fusionはコンパイル時に、空のget/setスタブを、実際のネットワーク状態データにアクセスするコードに置き換えます。直接アクセスすることで、メモリ割り当てのオーバーヘッドがなくなり、最適なパフォーマンスが得られます。絶対 に手動で実装しないでください。

また、バッファに直接アクセスすることで、変更があったときにはすぐにプロパ ティにその変更が反映されます。

ネットワーク状態に影響を与えるロジックを書くには、FixedUpdateNetwork()をオーバーライドして実装してください。

public override void FixedUpdateNetwork() {
    Health += Runner.DeltaTime * HealthRegen;
}

トップに戻る

制約事項

[Networked]プロパティは、以下の制約に従わなければなりません。

  • プロパティは、空の get/set ペアを持たなければならない。
  • 以下のタイプのみを含むことができる。

    • プリミティブ型(完全なリストは下記参照)
    • Unity型(完全なリストは下記参照)
    • INetworkStructを実装した、トップレベルで定義された構造体(つまり、クラス内でネストできない)
    • ネットワーク構造体へのポインター
    • [Capacity]属性で設定された最大長の文字列 (デフォルトは16)
    • NetworkObject
    • NetworkBehaviour のサブクラス
    • 最大の長さは [Capacity]属性を使用して設定される (デフォルトは1)。
    • ブール値の場合は、boolではなくNetworkBoolを使用。C# では、プラットフォーム間で bool のサイズを統一していないため、NetworkBool を使用して 1 ビットとして適切にシリアライズ。

    利用可能なプリミティブ型は以下の通りです。

    • byte, sbyte
    • Int16、Int32、Int64
    • UInt16, UInt32, UInt64
    • float
    • double

利用可能なUnityの型は以下の通りです。

  • Vector2, Vector3, Vector4
  • Quaternion
  • Matrix4x4
  • BoundingSphere
  • Bounds
  • Rect
  • Color
  • Vector2Int, Vector3Int
  • BoundsInt
  • RectInt
  • Color32

トップに戻る

Attributes

個々の数値型プロパティの精度は、[Accuracy]属性を用いて制御することが可能です。

public class PlayerBehaviour : NetworkedBehaviour {
  [Networked, Accuracy(0.001)]
  public float Health { get; set; }
}

[Capacity] は、NetworkArrayや文字列の最大長を定義するのに使われます。これらの型をFusionがネットワーク化するには、最大長を設定する必要があります。

[Capacity(14)] string MyString { get; set; }
[Capacity(8)]  NetworkArray<byte> MyArray { get; }

トップに戻る

OnChangedに反応

Fusionでは、ネットワーク化されたプロパティが変更されたときに、ゲームコードを起動することができます。リアクティブなコードを書くには、[Networked]属性の(OnChanged)パラメータを使います。

public class Powerup : NetworkBehaviour{
    [Networked(OnChanged = nameof(OnTypeChanged))] public Type type { get; set; }

    // Has to be public static void
    public static void OnTypeChanged(Changed<Powerup> changed){
        changed.Behaviour.OnTypeChanged();
    }

    private void OnTypeChanged(){
        // Some logic reacting to the value change of the "type" property
    }
}

コールバックの名前を指定するだけでなく、どのマシンでコールバックが実行されるかを制御することも可能です。

  • OnChangedLocal (default false): true に設定すると、プロパティを変更したマシンでもイベントフックが呼び出されるようになります。
  • OnChangedRemote (default true): false に設定すると、プロパティを変更したマシンでのみイベントフックが呼び出されます。

トップに戻る

オーバーライド可能なメソッド

NetworkObjectには、いくつかのライフサイクルメソッドが追加されており、これらはすべて、SimulationBehaviourNetworkBehaviourを実装する際にオーバーライドすることができます。

関数 説明
FixedUpdateNetwork() Fusionの固定タイムステップのコールバックです。ゲームのコアロジックに使用します。
Spawned() ポストスポーンのコールバック
Despawned(bool hasState) ネットワークオブジェクトがデスポーンされる前に呼び出されます。
---
bool hasState: 動作の状態にまだアクセスできるかどうか。
Render() シミュレーション後のフレームレンダリングコールバック。すべてのシミュレーションが終了した後に実行されます。Fusionが物理演算を行う場合、UnityのUpdateの代わりに使用します。

トップに戻る

FixedUpdateNetwork

FixedUpdateNetwork()(FUN()と略されます)は、あるティックから次のティックへと新しい状態をシミュレートするときに呼び出されます。この間隔のタイムステップは、NetworkProjectConfigアセットのSimulation > Tick Rateで定義されます。このタイムステップは、任意の SimulationBehaviourNetworkBehaviour から、Runner.DeltaTime プロパティを使ってアクセスできます。

FixedUpdateNetwork()は、同じ状態遷移に対して複数回呼び出すことができ、サーバーから受信した更新情報(ground truth)に基づいて、現在の予測状態を再シミュレーションします。 [Networked] のプロパティでは、再シミュレーションは透過的です。なぜなら、Fusionは再シミュレーションのためにFixedUpdateNetwork()を呼び出す前に、ネットワークの状態をリセットするからです。

重要: ネットワーク化されていない通常のローカルな状態変数(クラスメンバーなど)はリセットされず、単に状態の進行が追加されたとみなされます。

ドキュメントのトップへ戻る