アンリアルで C++ でマルチプレイヤーゲームを作ってみよう
2018年1月1日

アンリアルで C++ でマルチプレイヤーゲームを作ってみよう

作成 Sam Pattuzzi

 

マルチプレイヤーゲームをこよまく愛するファンのみなさん。世界中のプレイヤー達とプレイするだけでは物足りず、いっそのこと自分で作ってしまいたい!でもマルチプレイヤーはゲームの中でも最も難しいから無理に違いない、としり込みしていませんか?

非常にパワフルなエンジンであるアンリアルなら、マルチプレイヤーゲームに対応した数々の素晴らしい機能をすぐに使用することができます。みなさんが自作のマルチプレイヤーゲームに着手するための一歩を踏み出せるように、このブログで「入門ガイド」を書かせて頂きました。

内容は、Udemy で開講されている非常に詳しい講座の概要です。Udemy コースはビデオと練習で構成された 23 時間の学習カリキュラムを通じて、マルチプレイヤーゲーム作成のコンセプトをじっくり確実に学ぶことができます (コースの詳細は記事の最後に出てきます)。

正しいツールの選択

マルチプレイヤーは他のゲームとまったく違うため、もちろん要件も異なります。アンリアルは任意のマルチプレイヤーゲームに対して最適化されています。かといって、他のゲームに使えないわけではありません。追加のツールを使えばもちろん対応できます。

UdemyC++UE_Chart.png

* MMO タイプのゲームの場合は Improbable.io をチェックしてみてください。アンリアルと統合しており、MMO の複雑な部分を簡単に処理することができます。

アンリアルは同期ゲームプレイを含むショートセッションのゲームをいとも簡単に作成することができます。つまり、FPS、バトルロイヤル、レーシングゲーム、望むのであれば マイクラフトにインスパイアードされたサンドボックス といったジャンルさえも、非常に簡単に作成することができます。可能性は無限です。

アンリアルが提供するマルチプレイヤー向けサポートをマルチプレイヤー ゲームの 3 つのライフタイムにわけて説明します。

  1. Discovery (発見)
  2. Connection (接続)
  3. Synchronisation (同期)

アンリアルを使うと簡単にできる理由

UdemyC++UE_Inset.jpgアンリアルを使うと、あれほど大変なテスティング接続を非常に簡単に行うことができます。FPS のサンプルで始めるために、Play を押して、必要プレイヤー数を選択し、New Editor Window を押せば FPS のサンプルを開始することができます。

なぜそこまで簡単にできるのでしょうか?それは、アンリアルには様々な困難な処理を行うコンポーネントが数多く備わっているからです。

アンリアルの処理は以下のような処理をしています。

  1. アンリアルは マップをロードする
  2.  マップ が GameModeを指定する
  3.  PlayerController が マップと連携する
  4. PlayerController が GameMode に ポーンをスポーンするよう指示する
  5.  ポーン が PlayerController にリンクする

因みに、この操作はネットワーク上でも可能です。

ネットワーク接続のセットアップ

ネットワーク接続もアンリアルを使えば非常に簡単です。コマンドライン上でゲームを起動させると簡単に始めることができます。windows ではcommand prompt またはpowershell、Mac ではTerminal Appを使用します。

サーバーの起動には以下のラインを使います。ポートは自由に変更できますので、uproject とマップへのパスを正しく入力してください。

"C:\Program Files\UE_4.17\Engine\Binaries\Win64\UE4Editor.exe" 
"C:\PATH_TO_MY_PROJECT.uproject"
/Game/ThirdPersonCPP/Maps/ThirdPersonExampleMap -server -log -port=8003

サーバーが起動したら、次はクライアントへつなぎますが、これもとても簡単です。クライアントへの接続にはマップ入力ではなく、Player_Controller のIPアドレスが必要になることにご注意ください。IPアドレスとポートを正しく入力してください。

"C:\Program Files\UE_4.17\Engine\Binaries\Win64\UE4Editor.exe" 
"C:\PATH_TO_MY_PROJECT.uproject" 192.168.1.90:8003 -game -log

Mac の場合はパスが若干異なりますが、その他はほぼ一緒です。

移動のしくみ

 ServerTravel and ClientTravel 関数を用いることで、手間のかかる処理をユーザーに変わって行ってくれる UI を作成することができます。

基本的にはプレイヤー コントローラーをあるマップから切断して別のものに再接続するのですが、ServerTravel が接続しているすべての PlayerController (ネットワーク接続されているものも含む) を新しいマップに移動します。Client_Travel は PlayerController 側の処理なので、そのコントローラーのみを移動させます。

UdemyC++UE_ServerTravel.jpg

実際には、ServerTravelを使って"?listen" ストリングをマップURLの最後に追加することでマッチをホストします。そして ClientTravel 関数を使ってクライアントがマッチに参加できるようにします。

IPアドレスがパブリックにアクセス可能であれば良いのですが、実際には NAT 問題があります。従って、もしこれを避けたいのであれば、ポートを前もって設定するか、無料で使いやすい Hamachi などの仮想VPNソリューションを使用する必要があります。

ただ、仮想VPNはもちろん、IPアドレスのためにプレイヤーに煩わしい思いをさせたくはありません。そこで NAT traverral と呼ばれる処理をしてくれるサービスが必要です。

Steamworks SDK

嬉しいことに、SteamがNAT _traversal をSteamworks SDKの一環として無料で提供しています。この SDK は、プラットフォームにとらわれない  Online Sub-System (略して OSS)というレイヤーによりアンリアルとしっかり統合しています。

Steamworks にもマルチプレイヤーゲームの最初のステップである  Discovery (発見) に役立つソリューションが備わっています。ゲームとプレイヤーサーバーリストの宣伝を可能にする機能です。これは実際にコース中に作成したサーバーリストUIです。Donkey という名前のサーバーが表示されていますね。

UdemyC++UE_JoinAGame.jpg

権威のあるサーバーモデル

 Discovery と Connection については分かりましたでしょうか?では次は 同期について説明します。

サーバーはよく耳にはする言葉でありながら、その役割についてはあまりよく調べないものです。アンリアルでゲームを作る場合、サーバーは最も重要な難問です。なぜなら全員が納得し、だれもずるをしていないことを確実にする大役を果たすからです。つまり審判だとお考えください。

UdemyC++UE_ClientServer.jpg

上の表で、サーバーが1人のクライアントからアクションを受け取って(赤い稲妻印の部分)、そのステートを変更し、それをすべてのクライアントへ送信しています。

キャラクター移動コンポーネントを使用する際には、これらすべての同期はすでに書き込まれています。ただし、違う種類の移動を作り出すには、内部の仕組みを理解しなければなりません。

基本的な同期ツール

アクタは同期の基本単位で、クライアントとサーバーの両方に存在します。そしてサーバー側のアクタが  Authority Role  となるように指示されます。つまりこのアクタのバージョンが正しいとされます。そのアクタが特定のクライアントによって制御される場合を除き、他のクライアントは SimkulatedProxy role となります。アクタがローカルで制御される場合、Actor role は AutonomousProxyとなります。これらのroleにより、Actor コードは様々な端末上で異なる挙動をすることが可能になります。

同期するためには、AutonomousProxy クライアントがサーバーにデータを送るということが重要です。そしてサーバーがそのステートをアップデートした後で、必要なステートがクライアントに送信されます。前者は RPC コール、後者はレプリケートされたプロパティで行われます。この仕組みは非常に説明が長くなりますので割愛いたしますが、コースではじっくり学習することができます。

UdemyC++_UE_Ufunction.jpg

RPC コール は、ローカルに呼び出してサーバー上で関数を実行します。このメソッドによりサーバー上でのステートの変更が可能になります。コールは 検証関数を用いルールに従ってゲームを注意深く監視するのでずるはできません。詳細はコースで説明しています。

UdemyC++UE_UProperty.jpg

プロパティの複製は RPC よりもっと簡単です。UPROPERTY に "Replicated" 属性を追加し、UPROPERT 仮想メソッドに "Replicated" 属性、 GetLifetimeReplicatedProps に常用文を追加するだけです。 詳細な手順 については Wiki ページをご覧ください。

これで、魔法のように自動的に処理されます。プロパティが変更されれば、それに一致するようにクライアント側でアップデートされます。ただし、瞬時に行われるわけではありません。光ですら、世界一周するには時間がかかりますから。従って、クライアントはサーバーがアップデートしている間に何かしなければなりません。

そう、ここからは正念場なのです。

ゲーマーにとってラグというものは最悪の事態であり、ゲーム プログラマーにとってもラグへの対応は悪夢そのものです。

UdemyC++UE_Lag.jpg

ユーザーとサーバー間でのすべての処理によって発生します。ルーターは処理と付随するパケットをコピー、サーバーは計算を超高速で行わなければなりません。サーバーからの応答を得るのに実際 100ms かかります。

キーを叩いてからアクションの結果を見るまで 100ms もかかることはあり得ません。それではゲームが成り立ちません。そのため、クライアントがゲームももっとスムーズに遅延なしにスムーズに見えるようにする技術があります。作成するゲーム体験によってトレードオフがあるため、使用する技術は異なります。

実際、ラグが長くなってもFPSサンプルがうまく動くように CharacterMoveComponent にはいずれかの技術が実装されています。ただし、移動をカスタムしたいのであれば、これらの実装方法を学習しなければなりません。

残念ながらこの記事では技術を説明することはできませんが、コースの最後のセクションでは、まったくラグが発生しない動きをするゴーカートのアクタを作成しながらじっくり理解することができます。

コースのご紹介

なんとなくイメージが伝わりましたでしょうか?是非ご意見をお聞かせください。

本記事では駆け足での説明になってしまいましたが、我々が Udemy で提供している講座は、細かいところまでしっかりと理解するようにできています。20 時間かけて動画コンテンツでじっくり学習しながら、2 種類の基本的なマルチプレイヤー ゲームを実際に作り上げてきます。

最終的には、以下の内容を習得することができます。

  • ネットワーク関連の課題 (レイテンシー、パケットドロップ、NAT トラバーサルなど) に対する基本的な理解
  • アンリアルのマルチプレイヤー機能のアーキテクチャの理解
  • ローカルネットワーク上でのゲームインスタンスの接続
  • Steam プラグインおよびAPIを用いた、インターネット上でのプレイヤーの接続
  • ズルができないゲームの構築
  • RPCとプロパティレプリケーションを用いた、端末間での通信
  • 移動システムのカスタム用のラグ補正システムのビルド
  • API 機能を明確化するためのエンジンコードの解読方法

我々が Udemyコースで初めて開講したアンリアルコースの受講者数は10万人以上に達しました。今回の新しいコースも、我々の工夫と熱意を実感して頂けると思います。ネットワークのコンセプトが まったくなくても、アンリアルでシンプルなゲームができるようになります

C++ マルチプレイヤーコースについてはエピック ジャパンは全体のレビューをしておりませんが、 4000人 が受講しており、 5 段階中 4.8 の評価を受けています。このコースではネットワーク構築とマルチプレイヤーゲームの基礎を学習することができます。

UdemyC++UE_CourceButton.jpg

新年のセールが開催されているため、現在、90% オフの 2300円で購入することができます。この機会にぜひ利用してみてはいかがでしょうか。