ブループリントのマルチプレイヤー機能

ブループリントに適用するマルチプレイヤーの各種特定

Choose your operating system:

Windows

macOS

Linux

Unreal Engine 4 は、すぐに使用できる多数のマルチプレイヤー機能を内蔵しており、ネットワーク上で機能する基本的なブループリントゲームの設定を簡単に行うことができます。 すぐに作業を開始 してマルチプレイヤー ゲームをプレイできます。マルチプレイヤーを動かす基本的なロジックのほとんどは Character クラスに内蔵されたネットワーキング サポートと、クラスの CharacterMovementComponent のお陰です。これはサードパーソン テンプレート プロジェクトで使用されます。

ゲームプレイ フレームワークのおさらい

ゲームにマルチプレイヤー機能を追加するには、エンジンが提供する主なゲームプレイ クラスの役割およびこれらが互いに機能する方法を理解することが必要です。特にマルチプレイヤー コンテキストでこれらが機能する方法が重要です。

  • GameInstance

  • GameMode

  • GameState

  • ポーン (および ポーンから継承するキャラクター)

  • PlayerController

  • PlayerState

詳細は「 フレームワークのオンライン マニュアル 」を参照してください。マルチプレイヤー機能を持つゲームをデザインする時は、すくなくとも以下の点に留意してください。

  • GameInstance はエンジンのセッション中のみ存在します。つまり、エンジンが起動すると作成され、エンジンの電源を落とすまで破壊もしくは差し替えは行われません。サーバーと各クライアント上には別の GameInstance が存在しています。これらのインスタンスはお互いに通信しません。GameInstance はゲーム セッションの間以外も存在し、レベルのロード中に存在し続ける唯一のゲームの仕組みです。プレイヤーのライフタイム統計情報 (勝利者数)、アカウント情報 (特定アイテムの Locked/Unlocked のステータス)、さらに Unreal Tournament など競争するゲームのマップをいろいろと回って歩く種類の永続データを格納するのに適した場所です。

  • GameMode オブジェクトはサーバーのみに存在します通常、クライアントが明示的に知る必要のないゲーム関連情報を格納します。例えば、ゲームに "rocket launchers only (ロケットランチャーのみ)" という特別のルールがあったとしても、クライアントはこのルールを知る必要はありません。しかし、マップ周辺で武器を無作為にスポーンする時にサーバーは "rocket launcher" カテゴリからのみ選択することを知る必要があります。

  • GameState はサーバーとクライアントの両方に存在します。そのためサーバーはGameState でレプリケートした変数を使用して、ゲーム関連のデータ上で全てのクライアントを最新に保つことができます。すべてのプレイヤーおよび観戦者に関係しても、ある特定のプレイヤー対して関連性がないタイプの情報は GameState のレプリケーションに理想的です。例えば、野球ゲームは各チームのスコアと現在のイニングを GameState を使ってレプリケートします。

  • そのマシン上の 1 プレイヤーにつき、各クライアントに PlayerController が 1 つ存在します。これらはサーバーとサーバーに関連づいているクライアントの間でレプリケートされ、他のクライアントに対してはレプリケートされません。その結果、サーバーは各プレイヤーに対して PlayerControllers を持ちますが、ローカル クライアントはそれぞれのローカル プレイヤーの PlayerControllers しか所有しません。PlayerControllers はクライアントの接続中は存在し、ポーンと関連づいています。ただし、ポーンが頻繁に破壊やリスポーンされても PlayerControllers は影響を受けません。そのプレイヤーだけが探知するゲーム イベントに反応してサーバーがクライアントにミニマップにピンするように伝えるなど、他のクライアントにはこの情報の差し替えを行わずにクライアントとサーバー間でやりとりする場合にとても適しています。

  • PlayerState は、ゲームと接続しているすべてのプレイヤーに対してサーバーとクライアント両方に存在します。このクラスは、プレイヤーごとの現在のスコアなど、所有しているクライアントだけでなく、すべてのクライアントに関係するレプリケート プロパティに使用することができます。PlayerController と同様に、個々のポーンと関連づいていますが、ポーンが破壊またはリスポーンされても影響は受けません。

  • ポーン (キャラクターを含む) もサーバーとすべてのクライアント上に存在し、レプリケートした変数とイベントを格納することも出来ます。特定の変数またはイベントに PlayerState または Pawn を使用する決定は状況によりますが、PlayerController および PlayerState は、所有権を有するプレイヤーのゲーム接続中はずっと存在し、ゲームには新しいレベルがロードされませんが、 Pawn は接続中でも存続しない可能性があることを念頭に置いてください。例えば、ゲームプレイ中に死んだポーンは通常は破壊され新しいポーンに変わりますが、PlayerController と PlayerState は存在し続け、スポーンが完了した時に新しいポーンに関連づけられます。ポーンのヘルス値はポーンの実際のインスタンスに固有であり、ポーンが新しいポーンに変わるとリセットされるため、ポーンそのものに格納されます。

アクタのレプリケーション

replicates.png

UE4 のネットワークの構築のコア テクノロジーはアクタのレプリケーションです。 Replicates フラグを true に設定しているアクタは、サーバーが自身と接続しているクライアントへ自動的に同期します。アクタはサーバーからクライアントへのみレプリケートされることを理解しておくのが重要なポイントです。クライアントからサーバーへは不可能です。言うまでもなくクライアントはサーバーへデータを送信しなくてはいけません。データはレプリケートした "Run on server" イベントを通じて送信します。

具体例は「 ブループリントでアクタをレプリケートする 」および「 アクタのレプリケーション 」を参照してください。

権限

ワールド内のすべてのアクタは、接続するプレイヤーの 1 人がこのアクタに対する権限を有すると考えられます。サーバーに存在するすべてのアクタは、サーバーがこのアクタに対する権限を持ちます (レプリケートしたアクタすべてを含む)。結果として Has Authority 関数をクライアントで実行すると、その時のターゲットがクライアントにレプリケートされたアクタだと false を返します。また、別のサーバーやレプリケートしたアクタのクライアント ビヘイビアを分岐させる簡単な方法として、便利な Switch Has Authority マクロを使用することもできます。

switch_has_authority.png

変数

アクタの変数の詳細パネルにある [Replication] ドロップダウン リストを使って変数のレプリケート方法を調整することができます。

variable_replication.png

オプション

説明

None

新しい変数のデフォルト設定です。つまり値はネットワーク経由でクライアントへ送信されません。

Replicated

サーバーがこのアクタをレプリケートすると、この変数がクライアントへ送信されます。受け取るクライアント側の変数の値は自動的に更新されます。従って、次にアクセスした時にサーバー上の値に反映します。リアルワールド ネットワーク上でプレイ中は、更新にネットワークのレイテンシーに応じた遅延時間が発生します。レプリケートされた値はサーバーからクライアントへの一方通行であることを思い出してください。クライアントからサーバーへデータを送る方法は、『Events』 セクションをご覧ください。

RepNotify

変数は [replicated] オプションと同様にレプリケートしますが、 OnRep_<variable name> 関数はブループリントで作成します。この関数は、この変数の値が変更されるたびに、エンジンによってクライアントおよびサーバー上に自動的に呼び出されます。この関数はゲームの必要に応じて、自由に実装することができます。 onrep.png

エンジンに組み込まれているクラス内の変数のほとんどはレプリケーションが既に有効になっているので、ほとんどの機能はマルチプレイヤーの場合、自動的に動きます。

変数をレプリケーションするワークスルー「 ハウツーガイド 」と「 プロパティの完全レプリケーション 」を参照してください。

スポーンと破壊

レプリケートしたアクタをサーバーでスポーンすると、この動作はクライアントに伝達されて、クライアントもこのアクタのコピーを自動的にスポーンします。ただし一般的には、レプリケーションはクライアントからサーバーへ作成することはないため、レプリケートしたアクタがクライアントでスポーンされると、アクタはスポーンされたクライアントのみに存在します。サーバーもその他のクライアントも、アクタのコピーを受け取りません。一方で、スポーンしたクライアントはアクタに対する権限を持ちます。これはゲームプレイにほとんど影響しない表面的なアクタなどには有効ですが、ゲームプレイに影響を及ぼしたりレプリケートが必要なアクタは、サーバーで確実にスポーンすることをお勧めします。

サーバー上のアクタが破壊されると、すべてのクライアントは対応するアクタのコピーを破壊します。レプリケートされたアクタの破壊と似ています。クライアントは自身が権限を持つアクタを自由に破壊できます。つまり、他のプレイヤーにレプリケートされず、影響を受けることもない、アクタ自身がスポーンしたアクタを破壊できます。クライアントが権限を持たないアクタを破壊しようとすると、破壊リクエストは無視されます。ここでの重要なポイントは、レプリケートしたアクタの破壊はサーバー上で行われるということです。これはアクタをスポーンする場合も同様です。

イベントのレプリケーション

ブループリントは、アクタとその変数のレプリケーションの作成に加えて、クライアントとサーバー全体でイベントを実行することができます。

詳細は「 ブループリントで関数をレプリケーションする方法 」と「 RPC について 」を参照してください。

RPC (リモート プロシージャ コール) の用語も併せてチェックしてみてください。ブループリントでレプリケートしたイベントは実質的にエンジン内部の RPC へコンパイルされて、これらが通常 C++ コードで呼び出されることに注意してください。

オーナーシップ

レプリケートしたイベントを含むマルチプレイヤー ゲームの作業で理解すべき重要なコンセプトは、 指定アクタまたはコンポーネントのオーナーとみなされる 接続はどれかという点です。目的を果たすために、"Run on server" イベントはクライアントが所有するアクタ (またはアクタのコンポーネント) からのみ呼び出し可能な点に留意してください。通常は以下のアクタまたはアクタの 1 つのコンポーネントからのみ "Run on server" イベントを送信できることを意味します。

  • クライアントの PlayerController 自身

  • クライアントの PlayerController が所有するポーン、または

  • クライアントの PlayerState

同様に "Run on owning client" イベントを送信するサーバーに対し、いずれかのアクタでこれらのイベントも起動しなくてはいけません。そうしないと、サーバーはイベントを送信するクライアントが分からないため、イベントはサーバー上のみで実行します!

イベント

カスタムイベントの詳細パネルで、イベントのレプリケート方法を設定出来ます。

event_replication.png

オプション

説明

Not Replicated

デフォルト設定です。つまりこのイベントに対してレプリケーションは作成されません。クライアント上で呼び出されるとクライアント上でのみ実行され、サーバー上で呼び出されるとサーバー上でのみ実行されます。

Multicast

マルチキャストイベントがサーバーに呼び出された場合は、ターゲットオブジェクトを所有する接続先に関係なく、イベントはすべての接続クライアントにレプリケートされます。クライアントがマルチキャスト イベントを呼び出した場合は、イベントはレプリケートされていないかのように扱われて、呼び出し元のクライアントのみで実行されます。

Run on Server

このイベントがサーバーから呼び出された場合は、イベントはサーバーのみで実行されます。クライアントが所有するターゲットと一緒にイベントがクライアントから呼び出されると、イベントはサーバーへレプリケートされてここで実行されます。"Run on Server" イベントはクライアントがサーバーへデータを送信するための基本的なメソッドです。

Run on Owning Client

サーバーから呼び出されると、このイベントはターゲット アクタを所有するクライアントで実行されます。サーバーはアクタそのものを所有するので、"Run on Owning Client" イベントは (名前の意に反して) 実際はサーバー上で実行される場合があります。クライアントから呼び出された場合、イベントはレプリケートされていないかのように扱われて、呼び出し元のクライアントのみで実行されます。

以下の表は、呼ばれ方次第ではイベントの実行場所に影響を及ぼすさまざまなレプリケーションモードを示しています。

サーバーからイベントを呼び出した場合、左側のカラムをターゲットと仮定、そしてイベントの実行場所を順に表示しています。

Not replicated

Multicast

Run on Server

Run on Owning Client

Client-owned target

サーバー

サーバーとすべてのクライアント

サーバー

ターゲットが所有するクライアント

Server-owned target

サーバー

サーバーとすべてのクライアント

サーバー

サーバー

Unowned target

サーバー

サーバーとすべてのクライアント

サーバー

サーバー

クライアントからイベントを呼び出した場合、左側のカラムをターゲットと仮定、そしてイベントの実行場所を順に表示しています。

Not replicated

Multicast

Run on Server

Run on Owning Client

Target owned by invoking client

クライアントを呼び出し

クライアントを呼び出し

サーバー

クライアントを呼び出し

Target owned by a different client

クライアントを呼び出し

クライアントを呼び出し

ドロップ

クライアントを呼び出し

Server-owned target

クライアントを呼び出し

クライアントを呼び出し

ドロップ

クライアントを呼び出し

Unowned target

Iクライアントを呼び出し

クライアントを呼び出し

ドロップ

クライアントを呼び出しt

上記の表からもわかるように、クライアントから呼び出されて Run on Server を設定していないイベントは、レプリケートされていないかのように扱われます。

通常のアクタレプリケーションは「サーバーからクライアントへ」の一方向に設計されているため、レプリケートしたイベントの送信は、クライアントからサーバーへ情報を通信できる唯一の手段です。

マルチキャスト イベントはサーバーのみが送信可能であることにも留意してください。アンリアルのクライアント サーバー モデルを使用しているため、クライアントはその他のクライアントと直接接続していません。クライアントはサーバーだけと接続しています。そのため、クライアントはマルチキャスト イベントを直接他のクライアントへ送信することはできず、サーバーのみと通信しなくてはいけません。ただし、レプリケートした 2 つのイベントである Run on server イベントと Multicast イベントを使用すれば、このビヘイビアをエミュレートすることができます。Run on server イベントを実装することでバリデーションを実行して、必要に応じてマルチキャスト イベントを呼び出します。マルチキャスト イベントの実装は、接続しているすべてのプレイヤーで実行するロジックを実行します。以下の画像は、バリデーションを一切実行しない例です。

forward_multicast.png

進行中のゲームへの参加を検討

ゲームステート変更を通信するためにレプリケートイベントを使用する時は、イベントと「join-in-progress」 (進行中のゲームへの参加) をサポートするゲームがどのように相互作用するか注意してください。ゲームの進行中にプレイヤーがゲームに参加すると、参加前に発生したレプリケートイベントは新しいプレイヤーには実行されません。ゲームと「join-in-progress」をうまく機能させるには、レプリケートした変数で重要なゲームプレイデータを同期させるのが最善です。よくあるパターンとして、クライアントがワールドでいくつかのアクションを実行、 "Run on server" イベントでアクションをサーバーに通知、そしてこのイベントの実装で、サーバーはアクションに基づいてレプリケートした変数をいくつか更新します。アクションを実行しなかったその他のクライアントは、レプリケートした変数を通じてアクションの結果を知ることができます。またアクション発生後に「join-in-progress」したクライアントは、サーバーからレプリケートした変数の最新値を受け取るため、ワールドの正確なステートを知ることができます。代わりにサーバーのみがイベントを送信すると、「join-in-progress」プレイヤーは実行されたアクションを知ることができません!

Reliability (信頼性)

レプリケートしたイベントは、 Reliable または Unreliable のどちらかに設定できます。

Reliable イベントは目的地への到達が保証されているイベントですが、条件を満たすために多くの帯域幅を使用、およびレイテンシーが大きくなる可能性があります。Reliable イベントのエンジンの内部バッファがオーバーフローする可能性があるため、ティックの都度のように Reliable イベントの送信は頻繁にしないでください。オーバーフローが発生すると、関連するプレイヤーは非接続になってしまいます!

Unreliable イベントは名前が示す通りの機能を持ちます。つまり、ネットワーク上でパケットロスが発生した場合、またはネットワークに優先順位の高いトラフィックが多数存在すると判断した場合などは、イベントが目的地へ到達しない可能性があります。結果として、Unreliable イベントはReliable イベントよりも少ない帯域幅を使用し、より頻繁に安全に呼び出せます。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
閉じる