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

ネットワーク入力

はじめに

入力の定義、ポーリング、消費は、Fusionの中核をなすものです。

トップに戻る

入力構造体の定義

入力構造体には、必要に応じて単純なデータや複雑なデータを格納することができます。Fusionは実際に変化するデータのみを送信します。そのため、データはコンパクトにしておく方が有利ですが(例:ボタンにフラグを使う)、あまり使われないフィールドを含めても問題ありません。例えば、ローカル プレイヤーが基本1人しかいない場合でも、複数のローカルプレイヤーから入力を収集する場合です。これらのプレイヤーが実際に入力を行っていない場合は、入力構造体の帯域幅の使用には影響しませんが、ローカルメモリには影響します。

入力構造体には、次のような制約があります。

  • プリミティブな型と構造体のみを含むことができます。
  • 入力構造体とそれを保持する構造体は、トップレベルの構造体でなければならない(つまり、クラスの中にネストすることはできない)。
  • C# では、プラットフォーム間で bool のサイズを統一していないため、1 ビットとして適切に直列化するために、NetworkBool を使用します。
public struct MyGameInput : INetworkedInput {
  public const uint BUTTON_FORWARD  = 1 << 3;
  public const uint BUTTON_BACKWARD = 1 << 4;
  public const uint BUTTON_LEFT     = 1 << 5;
  public const uint BUTTON_RIGHT    = 1 << 6;

  public uint Buttons;

  public bool IsUp(uint button) {
    return IsDown(button) == false;
  }

  public bool IsDown(uint button) {
    return (Buttons & button) == button;
  }
}

Fusion は構造体の型をインテリジェントにマッピングします。これにより、プレイモードやゲームの各部分に応じて異なる構造体を使用することができます。入力をアンラップする際、Fusionは正しい型の入力のみを返します。

トップに戻る

入力ポーリング

Fusionはローカルクライアントをポーリングして入力を収集し、あらかじめ定義された 入力構造体を生成します。

SimulationBehaviour

Fusion は、INetworkRunnerCallbacks インターフェースを実装し、クライアントが 入力権限 を持つすべての SimulationBehaviour に対して、OnInput() を自動的に呼び出します(これが名前の由来です)。

トップに戻る

MonoBehaviourとPure CSharp

SimultionBehaviourを継承していないスクリプトからの入力をポーリングするには、以下の手順を実行します。

  1. InetworkRunnerCallbacksOnInput() を実装する。
  2. スクリプトの AddCallbacks() を呼び出して、スクリプトを NetworkRunner に登録する。
var myNetworkRunner = FindObjectOfType<NetworkRunner>();
myNetworkRunner.AddCallbacks( this );

トップに戻る

OnInput()

OnInput()の実装では、INetworkInputを継承する任意の構造体に、選択したデータを入力することができます。その後、生成された構造体は、提供された NetworkInput に対して Set() を呼び出すことで Fusion に返されます。

public class MyInput : SimulationBehaviour {
  public void OnInput(NetworkRunner runner, NetworkedInput inputContainer) {
    var myInput = new MyGameInput();

    if (Input.GetKey(KeyCode.W)) {
      myInput.Buttons |= MyGameInput.BUTTON_FORWARD;
    }

    if (Input.GetKey(KeyCode.S)) {
      myInput.Buttons |= MyGameInput.BUTTON_BACKWARD;
    }

    if (Input.GetKey(KeyCode.A)) {
      myInput.Buttons |= MyGameInput.BUTTON_LEFT;
    }

    if (Input.GetKey(KeyCode.D)) {
      myInput.Buttons |= MyGameInput.BUTTON_RIGHT;
    }

    inputContainer.Set(myInput);
  }
}

トップに戻る

入力の消費

入力の消費は、以前にポーリングされた入力に基づいて、既存のネットワーク状態を現在の状態から新しい状態に変更するためにシミュレーションで使用されます。Fusion は入力構造体をネットワーク上で同期させ、入力権限を持つクライアントと状態権限を持つもの(ホスト)がシミュレーション中に利用できるようにします。

GetInput()

入力構造体を取得するには、該当オブジェクトに対して入力権限を持つ任意の SimulationBehaviourFixedUpdateNetwork()の中で、GetInput()を呼び出します(例:プレイヤーの動きを制御するコンポーネント)。GetInput()を呼び出すと、以前にOnInput()で入力されたものと同じ入力構造体が提供されます。

public override void FixedUpdateNetwork()
{
    Vector3 direction = default;

    float rotate = 0;
    if (GetInput(out MyGameInput input))
    {
        if (input.IsDown(MyGameInput.BUTTON_FORWARD)) {
            direction += input.forward;
        } else if (input.IsDown(MyGameInput.BUTTON_BACKWARD)) {
            direction -= input.forward;
        }

        if (input.IsDown(MyGameInput.BUTTON_LEFT)) {
            rotate=-1;
        } else if (input.IsDown(MyGameInput.BUTTON_RIGHT)) {
            rotate=1;
        }

        if (input.IsDown(MyGameInput.BUTTON_JUMP)) {
            _player.Jump(); }
        if (input.IsDown(MyGameInput.BUTTON_FIRE)) {
            _player.Fire(_player.velocity); }

        _player.Move(direction);
        _player.Rotate(rotate);
    }
}

以下のいずれかが発生した場合、GetInput()の呼び出しはfalseを返します。

  • クライアントが状態の権限を持っていない。
  • クライアントが入力権限を持っていない。
  • 要求された入力タイプがシミュレーション内に存在しない。

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