41.3K Views
July 04, 17
スライド概要
2017年7月2日に行われたライセンシー様向けMO勉強会の資料です。基礎編 @ (登壇者: historia 原龍さま)
Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/
Multiplayer Online Deep Dive - Getting Started historia Inc. 原 龍 © historia Inc. #UE4DD
https://github.com/HogeTatu/UE4Plugin_WebApi © historia Inc. #UE4DD
本日の Deep Dive のお題目 Multiplayer Online © historia Inc. #UE4DD
Multiplayer Online (MO) 人数 プレイ時間 少人数(多くても30人程度) 短い(長くても60分程度) 求められるもの リアルタイム性が高い(低レイテンシ) ゲームデザイン • • • • アクション 格闘ゲーム FPS, TPS MOBA (Multiplayer Online Battle Arena) © historia Inc. #UE4DD
本日の流れ 導入(オンライン機能概要) Dedicated Server Traveling RPC / Replicate TCP Plugin はじめに、機能概要と Traveling 周りをヒストリアからご説明 © historia Inc. #UE4DD
本日の流れ 導入(オンライン機能概要) Dedicated Server Traveling RPC / Replicate TCP Plugin RPC / Replicate を中心に、バイキング様からご説明 © historia Inc. #UE4DD
本日の流れ 導入(オンライン機能概要) Dedicated Server Traveling RPC / Replicate TCP Plugin Dedicated Server を中心に、ソレイユ様からご説明 © historia Inc. #UE4DD
http://cedric-neukirchen.net/Downloads/Compendium/UE4_Network_Compendium_by_Cedric_eXi_Neukirchen.pdf 本日の内容は Cedric ‘eXi’ Neukirchen 様の資料を参考にさせて頂いています。 こちらも合わせてご確認頂けると、理解が進むと思われます。 © historia Inc. #UE4DD
ネットワークモード © historia Inc. #UE4DD
UE4 は Client-Server (C/S) モデル Server Client 1 Client 2 © historia Inc. ゲームプレイフローを制御 Client 3 #UE4DD
Listen Server (プレイヤーの1人がサーバーを担当) Server Client 1 Client 2 © historia Inc. Client 3 #UE4DD
Dedicated Server (専用のインスタンスがサーバーを担当) Server Client 1 Client 2 Client 3 © historia Inc. Client 4 #UE4DD
同期処理 1. Replicate (プロパティ同期) © historia Inc. #UE4DD
Actor のプロパティを C/S 間で同期
C++
/** 同期するプロパティ */
UPROPERTY(Replicated)
int32 SampleProperty;
/** 同期するプロパティを ActorChannel に通知 */
void ASampleActor::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ASampleActor, SampleProperty);
}
© historia Inc.
#UE4DD
Actor のプロパティを C/S 間で同期 Blueprint © historia Inc. #UE4DD
Actor のプロパティを C/S 間で同期後、コールバック通知 C++ /** 同期するプロパティ */ UPROPERTY(ReplicatedUsing=OnRep_SampleProperty) int32 SampleProperty; /** プロパティ同期通知コールバック */ UFUNCTION() void OnRep_SampleProperty(); ※ GetLifetimeReplicatedProps はコールバックの有無で変更なし © historia Inc. #UE4DD
Actor のプロパティを C/S 間で同期後、コールバック通知 Blueprint © historia Inc. #UE4DD
Actor Channel ? ▪ C/S 間で Actor と SubObject を同期するための通信チャンネル ▪ Actor のスポーン情報を持ち、レプリケートされた Actor の生成 / 破棄を管理する ▪ 所有する FObjectReplicator がプロパティ同期と RPC を行う © historia Inc. #UE4DD
Actor がレプリケートされる流れ Server Client Actor • • Actor • • • プロパティの差分抽出 リクエストされた RPC Actor Channel アクターの生成 プロパティの反映 RPC の実行 Actor Channel © historia Inc. #UE4DD
GetLifetimeReplicatedProps の役割 ▪ FObjectReplicator がパケットレイアウトを決めるために、 同期するプロパティを判断する際に利用される ▪ 同期するプロパティを設定しつつ、同期される条件(≒タイミング)を 指定することも可能 © historia Inc. #UE4DD
Actor のプロパティを同期する条件を指定
C++
/** 同期するプロパティ */
UPROPERTY(Replicated)
int32 SampleProp;
/** 同期するプロパティを ActorChannel に通知 */
void ASampleActor::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION(ASampleActor, SampleProp, COND_SkipOwner);
}
© historia Inc.
#UE4DD
Actor のプロパティを同期する条件を指定 Blueprint © historia Inc. #UE4DD
プロパティ同期条件一覧 ▪ COND_None ▪ COND_InitialOnly ▪ COND_OwnerOnly ▪ COND_SkipOwner ▪ COND_SimulatedOnly ▪ COND_AutonomousOnly ▪ COND_SimulatedOrPhysics ▪ 常時同期(条件なし) ▪ 初回同期もしくは Actor の所有者 初回同期のみ ▪ COND_SimulatedOnlyNoReplay Simulated のみ(リプレイ時は除く) Role=ROLE_AutonomousProxy のみ ▪ COND_ReplayOnly リプレイ時のみ Role=ROLE_SimulatedProxy のみ ▪ COND_ReplayOrOwner リプレイ時もしくは Actor の所有者 Actor の所有者以外 ▪ COND_Custom 条件をランタイムで変更できる ※詳しくは後述 Actor の所有者のみ ▪ COND_InitialOrOwner COND_SimulatedOrPhysicsNoReplay Simulated もしくは bRepPhysics のみ(リプレイ時は除く) Simulated もしくは bRepPhysics のみ COND_SkipReplay リプレイ時以外 © historia Inc. #UE4DD
COND_Custom C++ /** PreReplication で同期する条件を指定 */ void ASampleActor::PreReplication( IRepChangedPropertyTracker& ChangedPropertyTracker) { Super::PreReplication(ChangedPropertyTracker); DOREPLIFETIME_ACTIVE_OVERRIDE( ASampleActor, SampleProp, bReplicateSampleProp); } © historia Inc. #UE4DD
同期処理 2. RPC (Remote Procedure Call) © historia Inc. #UE4DD
Multicast (Server / 全 Client で実行) C++ /** Multicast */ UFUNCTION(NetMulticast, unreliable) void Multicast_SampleEvent(); void ASampleActor::Multicast_SampleEvent_Implementation() { } © historia Inc. #UE4DD
Multicast (Server / 全 Client で実行) Blueprint © historia Inc. #UE4DD
Run on Owning Client (Actor を所有する Client で実行) C++ /** Run on Owning Client */ UFUNCTION(Client, unreliable) void Client_SampleEvent(); void ASampleActor::Client_SampleEvent_Implementation() { } © historia Inc. #UE4DD
Run on Owning Client (Actor を所有する Client で実行) Blueprint © historia Inc. #UE4DD
Run on Server (Server で実行) C++ /** Run on Server */ UFUNCTION(Server, unreliable, WithValidation) void Server_SampleEvent(); void ASampleActor::Server_SampleEvent_Implementation() { } bool ASampleActor::Server_SampleEvent_Validate() { return true; } © historia Inc. #UE4DD
Run on Server (Server で実行) Blueprint © historia Inc. #UE4DD
WithValidation ▪ RPC で呼び出される関数を実行する直前に検証用の関数を実行する ▪ 関数名は RPCFunctionName_Validate で戻り値は boolean ▪ 戻り値で false を返すと RPC で呼び出された関数は実行されない © historia Inc. #UE4DD
Reliable ▪ RPC は UDP で通信する都合上、パケットの欠損や順序が不定になるといった ことが起こるため、確実に受信されてほしい処理には向いていない ▪ Reliable フラグを利用することで RPC 実行時に疎通確認を行い、 通信の信頼性を向上させる ことができる © historia Inc. #UE4DD
Reliable C++ /** Run on Server */ UFUNCTION(Client, reliable, WithValidation) void Server_SampleEvent(); Blueprint © historia Inc. #UE4DD
Actor の所有権 © historia Inc. #UE4DD
ここはUE4のマルチプレイを理解する上で重要な部分です (ハマりやすい部分です) © historia Inc. #UE4DD
Actor の所有権とは ▪ Server / Client は Actor に対して所有権を持つ ▪ AActor::Owner で所有権を持つかどうかを判断できる ▪ ただし Pawn の場合は APawn::IsLocallyControlled で判断する ▪ 所有権の有無によって、RPCの実行が制限されるケース が存在する © historia Inc. #UE4DD
RPCの実行が制限されるケース (Server で実行した場合) Actor 所有者 Multicast Run on Server Run on Owning Client Client Server / 全 Client で実行 Server で実行 所有する Client で実行 Server Server / 全 Client で実行 Server で実行 Server で実行 © historia Inc. #UE4DD
RPCの実行が制限されるケース (Client で実行した場合) Actor 所有者 Multicast Run on Server Run on Owning Client 自 Client 自 Client で実行 Server で実行 自 Client で実行 他 Client 自 Client で実行 実行されない 自 Client で実行 Server 自 Client で実行 実行されない 自 Client で実行 © historia Inc. #UE4DD
RPC が実行されないケース – (1) Server Server が所有する Actor RPC 呼び出し Client 1 Client 2 © historia Inc. #UE4DD
RPC が実行されないケース – (2) Server 他 Client が所有する Actor RPC 呼び出し Client 1 Client 2 © historia Inc. #UE4DD
なぜ所有権は必要? 所有者以外が悪意を持って 不正に Actor を操作する事への対処 © historia Inc. #UE4DD
所有権によるカテゴライズ ▪ Actor は全ての Server / Client にレプリケートされるわけではい ▪ Actor がどこにレプリケートされるかというカテゴライズは、 Actor のプロパティ設定を元に行われる © historia Inc. #UE4DD
Server Only Server Client 1 ▪ サーバーのみに生成されるアクター ▪ GameMode など Client 2 © historia Inc. #UE4DD
Server Only AServerOnlyActor::AServerOnlyActor() { // プレイヤーが持つコントロール権 Role = ROLE_Authority; // 他プレイヤーが持つコントロール権 RemoteRole = ROLE_None; // 同期対象フラグ bReplicates = false; // 所有権を持つクライアントのみに同期するフラグ bOnlyRelevantToOwner = false; } © historia Inc. #UE4DD
Server & Client ▪ Server サーバーと全てのクライアントに 生成されるアクター ▪ GameState, PlayerState など ▪ ほとんどのアクターはこの設定で サーバーが生成し、レプリケートされる Client 1 Client 2 © historia Inc. #UE4DD
Server & Client AServerClientActor::AServerClientActor() { // プレイヤーが持つコントロール権 Role = ROLE_Authority; // 他プレイヤーが持つコントロール権 RemoteRole = ROLE_SimulatedProxy; // 同期対象フラグ bReplicates = true; // 所有権を持つクライアントのみに同期するフラグ bOnlyRelevantToOwner = false; } © historia Inc. #UE4DD
Server & Client (所有者) ▪ Server サーバーと所有するクライアントのみに 生成されるアクター ▪ PlayerController, Possess している Pawn など Client 1 Client 2 © historia Inc. #UE4DD
Server & Client (所有者) AServerOwningClientActor::AServerOwningClientActor() { // プレイヤーが持つコントロール権 Role = ROLE_Authority; // 他プレイヤーが持つコントロール権 RemoteRole = ROLE_SimulatedProxy; // 同期対象フラグ bReplicates = true; // 所有権を持つクライアントのみに同期するフラグ bOnlyRelevantToOwner = true; } © historia Inc. #UE4DD
OnlineSubsystem © historia Inc. #UE4DD
各種SDK OnlineSubsystem ゲーム プラットフォームの APIを抽象化 • • • • • • • ログイン セッション管理 マッチング 実績 ランキング チャット ストア(課金) etc... © historia Inc. Steam PS4 Oculus Google Amazon Facebook #UE4DD
OnlineSubsystem の設計 ▪ 各プラットフォームは機能別に定義されたインターフェースを継承したクラスを実装する ▪ インターフェースは IOnline[機能名] で用意されている – ex. IOnlineAchievements ▪ 各プラットフォームは FOnline[機能名][プラットフォーム名] で実装する – ex. FOnlineAchievementSteam © historia Inc. #UE4DD
OnlineSubsystem で機能が足りていなかった場合は? ▪ 必要なインターフェースを継承しつつ、足りていない機能のクラスを新規作成する ▪ IOnlineSubsystem を継承しながら、プラットフォーム別に FOnlineSubsystem[プラットフォーム] が実装されているので、 各機能の実装を取得する Get[機能名]Interface で追加した機能の リファレンスを返すようにする © historia Inc. #UE4DD
© historia Inc. #UE4DD
ここからは開発フローについて © historia Inc. #UE4DD
ネットワーク対応ゲームの基本的なデプロイフロー QA Development ステージング サーバー 作業PC Release 開発サーバー 公開サーバー © historia Inc. #UE4DD
作業PC(ローカル) QA Development ステージング サーバー 作業PC Release 開発サーバー 公開サーバー © historia Inc. #UE4DD
ローカルでのマルチプレイプレビュー 1. PIE 起動 © historia Inc. #UE4DD
© historia Inc. #UE4DD
© historia Inc. #UE4DD
PIE 起動時に自動でマッチングされた状態にする Editor Preferences -> Level Editor -> Play -> Multiplayer Options -> Auto Connect To Server 単体のレベルでマルチプレイのデバッグを行うときに有効 © historia Inc. #UE4DD
Auto Connect To Server の注意点 ▪ 簡易的に Server / Client の設定だけ行ってプレビューを行っている ▪ つまり C/S 間で正式な手続き(Control Channel でのメッセージング) を行っていないため、レベル移動を行ってしまうと正常な結果にならない © historia Inc. #UE4DD
ローカルでのマルチプレイプレビュー 2. –game オプションで起動 © historia Inc. #UE4DD
UE4Editor.exe に uproject を指定して -game オプションを付けて起動すると、 Cook 無しスタンドアロン実行 が可能 © historia Inc. #UE4DD
起動バッチを作ると便利 @echo off set set set set set EDITOR_PATH=..¥Engine¥Binaries¥Win64¥UE4Editor.exe UPROJECT_NAME=MultiplayerOnlineDD.uproject SERVER_MAP_NAME=/Game/DeepDive/Maps/OpenUrl/OpenUrlServer CLIENT_MAP_NAME=/Game/DeepDive/Maps/OpenUrl/OpenUrlClient LAUNCH_PARAM=-game -ResX=640 -ResY=360 -WINDOWED start %EDITOR_PATH% %UPROJECT_NAME% %SERVER_MAP_NAME% %LAUNCH_PARAM% ^ -WinX=100 -WinY=100 -log -ConsoleX=100 -ConsoleY=500 start %EDITOR_PATH% %UPROJECT_NAME% %CLIENT_MAP_NAME% %LAUNCH_PARAM% ^ -WinX=800 -WinY=100 exit © historia Inc. #UE4DD
© historia Inc. #UE4DD
PIE 起動でのプレビューはあくまで単一プロセスでの実行で ダミー的に処理されている部分があるため、 デプロイ前には一度デバッグしておいた方が良い © historia Inc. #UE4DD
パケットシミュレーション © historia Inc. #UE4DD
ローカルプレビューではパケットの遅延等が全く発生せず、 実際にマシン間で通信する際に 意図した挙動にならないといった事が起こりえます © historia Inc. #UE4DD
ローカルプレビュー時にこのような状態を再現するため、 エミュレート用の各種デバッグコマンドが用意されています © historia Inc. #UE4DD
Net PktLoss=[Int] ▪ 確率でパケットを送信しない(消失シミュレーション) ▪ 単位は 0 – 100 % © historia Inc. #UE4DD
Net PktOrder=[Boolean] ▪ パケットをバッファリングして送信順序をランダムにする ▪ 単位は 0 – 1 © historia Inc. #UE4DD
Net PktLag=[Int] ▪ パケット送信時に遅延を発生させる(固定値) ▪ 単位はミリ秒 © historia Inc. #UE4DD
Net PktLagVariance=[Int] ▪ パケット送信時に遅延を発生させる(範囲ランダム値) ▪ 単位は ± ミリ秒 © historia Inc. #UE4DD
B.SendTime = FPlatformTime::Seconds() + (double(PacketSimulationSettings.PktLag) + 2.0f * (FMath::FRand() - 0.5f) * double(PacketSimulationSettings.PktLagVariance))/ 1000.f; © historia Inc. #UE4DD
Net PktDup=[Int] ▪ パケット送信時に確率で2回送信する(重複させる) ▪ 単位は 0 – 100 % © historia Inc. #UE4DD
この辺の実装は UNetConnection::FlushNet © historia Inc. #UE4DD
RPC のデバッグ © historia Inc. #UE4DD
net.RPC.Debug [Boolean] RPC 実行時のログを Warning で出力する 有効にした状態で LogNet でフィルターを設定すると Traveling や Replicate の流れがよく見える © historia Inc. #UE4DD
ネットワークプロファイラ © historia Inc. #UE4DD
ネットワークプロファイラ ▪ Replication, RPC に関するプロファイラ ▪ 帯域のボトルネックを調査する時に有用 ▪ Actor / Property / RPC でフィルタリングすることも可能 © historia Inc. #UE4DD
ネットワークプロファイラ ▪ netprofile enable/disable でプロファイリング状態を切り替える ▪ プロファイリング結果を確認するためには下記パスからツールを起動する – /Engine/Binaries/DotNET/NetworkProfiler.exe ▪ プロファイリング結果は下記ディレクトリに保存されている – /ProjectRoot/Saved/Profiling © historia Inc. #UE4DD
© historia Inc. #UE4DD
https://docs.unrealengine.com/latest/JPN/Gameplay/Tools/NetworkProfiler/index.html © historia Inc. #UE4DD
開発サーバー QA Development ステージング サーバー 作業PC Release 開発サーバー 公開サーバー © historia Inc. #UE4DD
パッケージ生成 © historia Inc. #UE4DD
UE4 では同一プロジェクトから各種パッケージを生成 UE4 Solution • Windows Client • Windows Server UE4 Project • PS4 Client • Linux Server Game Project etc ... © historia Inc. #UE4DD
Build Configuration ビルド名 [empty] ビルド概要 ビルドルールを指定するファイル スタンドアロンゲーム実行用のビルド ProjectName.Target.cs Editor エディタ実行用のビルド ProjectNameEditor.Target.cs Client マルチプレイゲームにおけるクライアント用のビルド ProjectNameClient.Target.cs Server マルチプレイゲームにおけるサーバー用のビルド ProjectNameServer.Target.cs © historia Inc. #UE4DD
© historia Inc. #UE4DD
© historia Inc. #UE4DD
ビルドジョブセットからまとめて各種ビルドを実行する Batch Builder (UnrealVS 拡張) が便利 © historia Inc. #UE4DD
Batch Builder はこのボタンから起動する © historia Inc. #UE4DD
https://docs.unrealengine.com/latest/JPN/Programming/Development/VisualStudioSetup/UnrealVS/index.html © historia Inc. #UE4DD
Client / Server ビルドで謎のコンパイルエラーが…? Client / Server ビルドは、ランチャーからインストールしたエンジンだとビルドできない仕様 (ProjectName.sln ではなく、UE4.sln からのみビルド可能) © historia Inc. #UE4DD
Cook は ProjectLauncher から行うと 複数パッケージを同時に生成できる © historia Inc. #UE4DD
Linux クロスコンパイル © historia Inc. #UE4DD
Linux クロスコンパイル未使用時 Windows 開発マシン Linux 開発サーバー • エディタで開発 • Linux Server ビルド • Windows Client ビルド • サーバー上でテスト • Windows Server ビルド デプロイ • ローカルテスト © historia Inc. #UE4DD
Linux クロスコンパイル未使用時 Windows 開発マシン Linux 開発サーバー • エディタで開発 • Linux Server ビルド • Windows Client ビルド • サーバー上でテスト • Windows Server ビルド デプロイ • ローカルテスト ビルドエラーで手戻りの可能性! © historia Inc. #UE4DD
Linux クロスコンパイル使用時 Windows 開発マシン Linux 開発サーバー • エディタで開発 • サーバー上でテスト • Windows Client ビルド • Windows Server ビルド デプロイ • ローカルテスト • Linux Server ビルド デプロイ先でのエラーを防ぐ © historia Inc. #UE4DD
https://docs.unrealengine.com/latest/JPN/Platforms/Linux/GettingStarted/index.html © historia Inc. #UE4DD
Linux クロスコンパイル時の注意点 ▪ 基本的には使用するUE4のバージョンに合わせたツールチェーンのダウンロードと、 環境変数の設定のみ ▪ 複数のUE4プロジェクトが混在していて環境変数を汚染したくない場合、 LINUX_MULTIARCH_ROOT を検索して置き換えることで対応は可能 (DedicatedServer を選択する以上、自ずとエンジンはソースコードビルドになるので・・・) © historia Inc. #UE4DD
まとめ ▪ MO ゲーム制作のための機能は一通り揃っている印象 ▪ ただしブラックボックスな部分が多く、実はできるのに知られていない機能や ini 設定、コンソールコマンドが用意されていたりする ▪ 実際の運用時には NetworkProfiler で細かく使用帯域を見ていく必要がある © historia Inc. #UE4DD