見出し画像

Unity NetCode 入門 (2) - クライアントワールドとサーバーワールド

以下の記事を参考にして書いてます。

Client server Worlds

1. クライアントワールドとサーバーワールド

「NetCode」では、クライアントとサーバーのロジックが分離されおり、別々のワールド(クライアントワールドとサーバーワールド)で管理されます。ワールドは、「ECS」で「EntityManager」と「System」をグループ化するもので、ワールド同士は直接アクセスすることができません。

デフォルトでは、「NetCode」はシステムをクライアントとサーバーの両方のワールドに配置しますが、デフォルトワールドには配置しません。「PresentationSystemGroup」で更新されるシステムは、クライアントワールドにのみ追加されます。このデフォルトの動作を上書きするには、 [UpdateInWorld]または[UpdateInGroup]を使用します。

使用可能な明示的なクライアントサーバーグループは、次のとおりです。

・ClientInitializationSystemGroup
・ServerInitializationSystemGroup
・ClientAndServerInitializationSystemGroup
・ClientSimulationSystemGroup
・ServerSimulationSystemGroup
・ClientAndServerSimulationSystemGroup
・ClientPresentationSystemGroup
【注意】「ServerPresentationSystemGroup」はありません。

上記の属性に加えて、Unityエディタの「PlayMode Tools」で、プレイモード時の動作を選択できます。メニュー「Multiplayer → PlayMode Tools」で「PlayMode Tools」を開くことができます。

画像1

◎ PlayMode Type
プレイモードをクライアントのみ、サーバーのみ、またはクライアントとサーバーのいずれかにすることを選択します。

◎ Num Clients
同じプロセスで実行するクライアントの数を設定します。複数のクライアントをプレイモードで実行し、すべてを別々のワールドで実行できます。

◎ Num Thin Clients
シンクライアントの数を設定します。シンクライアントは提示できず、サーバーから受信するエンティティを生成しません。ただし、実際の負荷をシミュレートするためにサーバーに送信する偽の入力を生成する可能性があります。

◎ Client send/recv delay
このプロパティを使用して、高pingをエミュレートします。各発信および着信ネットワークパケットを遅延させる時間(ミリ秒単位)を指定します。

◎ Client send/recv jitter
このプロパティを使用して、ランダムな値を遅延に追加します。これにより、遅延は、設定した遅延とジッタ値の差の間の値になります。たとえば、クライアントの送信/受信遅延を45に設定し、クライアントの送信/受信ジッタを5に設定すると、40〜50のランダムな値が取得されます。

◎ Client package drop
このプロパティを使用して、すべてのパケットが到着するわけではない不良接続をシミュレートします。値を(パーセンテージで)指定すると、NetCodeは受信した合計からそのパーセンテージのパケットを破棄します。たとえば、値を5に設定すると、NetCodeはすべての着信および発信パケットの5%を破棄します。

◎ Client auto connect address (Client only)
クライアントが接続するサーバーを指定します。このフィールドは、PlayMode TypeをClientに設定した場合にのみ表示されます。接続が流れるため、ユーザーコードはこの値を読み取って接続する必要があります

2. ブートストラップ

デフォルトの「ブートストラップ」は、起動時にクライアントワールドとサーバーワールドを自動的に作成します。設定した属性で定義されているシステムを使用してそれらを設定します。これはエディタで作業しているときに便利ですが、スタンドアロンゲームでは、ワールドの作成を遅らせて、クライアントとサーバーの両方を同じ実行ファイルで使用できるようにすることができます。

これを行うには、「ClientServerBootstrap」を拡張するクラスを作成して、デフォルトの「ブートストラップ」をオーバーライドします。初期化を実装し、デフォルトのワールドを作成します。クライアントワールドとサーバーワールドを手動で作成するには、以下を呼びます。

ClientServerBootstrap.CreateClientWorld(defaultWorld, "WorldName");
ClientServerBootstrap.CreateServerWorld(defaultWorld, "WorldName");

次のコード例は、デフォルトの「ブートストラップ」をオーバーライドして、「クライアントワールド」と「サーバーワールド」が自動的に作成されないようにする方法を示しています。

public class ExampleBootstrap : ClientServerBootstrap
{
    public override bool Initialize(string defaultWorldName)
    {
        var systems = DefaultWorldInitialization.GetAllSystems(WorldSystemFilterFlags.Default);
        GenerateSystemLists(systems);

        var world = new World(defaultWorldName);
        World.DefaultGameObjectInjectionWorld = world;

        DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups(world, ExplicitDefaultWorldSystems);
        ScriptBehaviourUpdateOrder.UpdatePlayerLoop(world);
        return true;
    }
}

3. 固定および動的タイムステップ

「NetCode」を使用すると、サーバーは常に固定タイムステップで更新されます。「NetCode」は、サーバーが単一フレームのシミュレーションに数秒かかる状態にならないように、反復の最大数を制限します。

修正された更新は、標準のUnity更新頻度を使用しません。サーバーワールドのシングルトンエンティティは、「ClientServerTickRateコンポーネント」を使用して更新を制御します。「ClientServerTickRate」は、1秒あたりのシミュレーションTick数を設定する「SimulationTickRate」を制御します。

【注意】SimulationTickRateはNetworkTickRateで割り切れる必要があります。

シミュレーションTickのデフォルト数は60です。コンポーネントには、サーバーが単一フレームで実行できるシミュレーションの数を制御するMaxSimulationStepsPerFrameの値と、サーバーがTickレートを維持する方法を制御するTargetFrameRateModeの値もあります。使用可能な値は次のとおりです。

・BusyWait : 最高速度で実行
・Sleep : Application.TargetFrameRateがCPU負荷を軽減
・Auto : ヘッドレスサーバーの場合はSleep、それ以外の場合はBusyWait

デフォルトでは、クライアントは動的タイムステップで更新されますが、サーバーと一致するように常に固定タイムステップで実行される予測コードは例外です。予測はGhostPredictionSystemGroupで実行され、独自の固定タイムステップを予測に適用します。クライアントに固定時間ステップを使用させるには、FixedClientTickRateコンポーネントを使用してシングルトンエントリを作成します。固定Tickレートを使用する場合は、CurrentSimulatedPositionおよびCurrentSimulatedRotationコンポーネントをエンティティに追加して、レンダリング補間を処理できます。

4. スタンドアロンビルド

スタンドアロンゲームをビルドする場合、「NetCode」はビルド設定ウィンドウのサーバービルドプロパティを使用して、何をビルドするかを決定します。プロパティが有効な場合、「NetCode」は「UNITY_SERVER定義」を設定し、サーバーのみのビルドを取得します。プロパティが無効な場合、クライアントとサーバーの組み合わせがビルドされます。クライアントとサーバーを組み合わせたビルドを使用して、ゲームを実行時にクライアント、サーバー、またはその両方にするかどうかを決定できます。クライアントのみのゲームを構築するには、「UNITY_CLIENT定義」をプレーヤー設定のスクリプト定義シンボルに追加します(メニュー「Edit → Project Settings → Player → Configuration)。サーバーをビルドする時に「UNITY_CLIENT定義」を設定できますが、「UNITY_SERVER定義」が優先され、サーバーのみのビルドを取得します。


この記事が気に入ったらサポートをしてみませんか?