Skip to main content
© historia Inc. #UE4DD
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
本日の流れ
TravelingDedicated Server
RPC / Replicate
導入(オンライン機能概要)
はじめに、機能概要と Traveling 周りをヒストリアからご説明
TCP
Plugin
© historia Inc. #UE4DD
本日の流れ
TravelingDedicated Server
RPC / Replicate
導入(オンライン機能概要)
RPC / Replicate を中心に、バイキング様からご説明
TCP
Plugin
© historia Inc. #UE4DD
本日の流れ
TravelingDedicated Server
RPC / Replicate
導入(オンライン機能概要)
Dedicated Server を中心に、ソレイユ様からご説明
TCP
Plugin
© 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) モデル
Client 1
Server
Client 2 Client 3
ゲームプレイフローを制御
© historia Inc. #UE4DD
Listen Server (プレイヤーの1人がサーバーを担当)
Client 1
Server
Client 2 Client 3
© historia Inc. #UE4DD
Dedicated Server (専用のインスタンスがサーバーを担当)
Client 1 Client 2 Client 3 Client 4
Server
© historia Inc. #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
Server Client
Actor
Actor Channel
Actor
Actor Channel
• プロパティの差分抽出
• リクエストされた RPC
• アクターの生成
• プロパティの反映
• RPC の実行
Actor がレプリケートされる流れ
© 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
Actor の所有者のみ
 COND_SkipOwner
Actor の所有者以外
 COND_SimulatedOnly
Role=ROLE_SimulatedProxy のみ
 COND_AutonomousOnly
Role=ROLE_AutonomousProxy のみ
 COND_SimulatedOrPhysics
Simulated もしくは bRepPhysics のみ
 COND_InitialOrOwner
初回同期もしくは Actor の所有者
 COND_Custom
条件をランタイムで変更できる ※詳しくは後述
 COND_ReplayOrOwner
リプレイ時もしくは Actor の所有者
 COND_ReplayOnly
リプレイ時のみ
 COND_SimulatedOnlyNoReplay
Simulated のみ(リプレイ時は除く)
 COND_SimulatedOrPhysicsNoReplay
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
Client 1 Client 2
Server が所有する Actor
RPC 呼び出し
© historia Inc. #UE4DD
RPC が実行されないケース – (2)
Server
Client 1 Client 2
他 Client が所有する Actor
RPC 呼び出し
© historia Inc. #UE4DD
なぜ所有権は必要?
所有者以外が悪意を持って
不正に Actor を操作する事への対処
© historia Inc. #UE4DD
所有権によるカテゴライズ
 Actor は全ての Server / Client にレプリケートされるわけではい
 Actor がどこにレプリケートされるかというカテゴライズは、
Actor のプロパティ設定を元に行われる
© historia Inc. #UE4DD
Client 1 Client 2
Server Only
Server
 サーバーのみに生成されるアクター
 GameMode など
© historia Inc. #UE4DD
Server Only
AServerOnlyActor::AServerOnlyActor()
{
// プレイヤーが持つコントロール権
Role = ROLE_Authority;
// 他プレイヤーが持つコントロール権
RemoteRole = ROLE_None;
// 同期対象フラグ
bReplicates = false;
// 所有権を持つクライアントのみに同期するフラグ
bOnlyRelevantToOwner = false;
}
© historia Inc. #UE4DD
Server
 サーバーと全てのクライアントに
生成されるアクター
 GameState, PlayerState など
 ほとんどのアクターはこの設定で
サーバーが生成し、レプリケートされる
Server & Client
Client 1 Client 2
© historia Inc. #UE4DD
AServerClientActor::AServerClientActor()
{
// プレイヤーが持つコントロール権
Role = ROLE_Authority;
// 他プレイヤーが持つコントロール権
RemoteRole = ROLE_SimulatedProxy;
// 同期対象フラグ
bReplicates = true;
// 所有権を持つクライアントのみに同期するフラグ
bOnlyRelevantToOwner = false;
}
Server & Client
© historia Inc. #UE4DD
Server
 サーバーと所有するクライアントのみに
生成されるアクター
 PlayerController,
Possess している Pawn など
Client 1 Client 2
Server & Client (所有者)
© historia Inc. #UE4DD
AServerOwningClientActor::AServerOwningClientActor()
{
// プレイヤーが持つコントロール権
Role = ROLE_Authority;
// 他プレイヤーが持つコントロール権
RemoteRole = ROLE_SimulatedProxy;
// 同期対象フラグ
bReplicates = true;
// 所有権を持つクライアントのみに同期するフラグ
bOnlyRelevantToOwner = true;
}
Server & Client (所有者)
© historia Inc. #UE4DD
OnlineSubsystem
© historia Inc. #UE4DD
ゲーム
OnlineSubsystem
• ログイン
• セッション管理
• マッチング
• 実績
• ランキング
• チャット
• ストア(課金)
etc...
Steam
PS4
Oculus
Google
Amazon
Facebook
プラットフォームの
APIを抽象化
各種SDK
© historia Inc. #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
Release
QADevelopment
ネットワーク対応ゲームの基本的なデプロイフロー
作業PC
開発サーバー
ステージング
サーバー
公開サーバー
© historia Inc. #UE4DD
Release
QADevelopment
作業PC
開発サーバー
ステージング
サーバー
公開サーバー
作業PC(ローカル)
© 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 EDITOR_PATH=..EngineBinariesWin64UE4Editor.exe
set UPROJECT_NAME=MultiplayerOnlineDD.uproject
set SERVER_MAP_NAME=/Game/DeepDive/Maps/OpenUrl/OpenUrlServer
set CLIENT_MAP_NAME=/Game/DeepDive/Maps/OpenUrl/OpenUrlClient
set 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
Release
QADevelopment
作業PC
開発サーバー
ステージング
サーバー
公開サーバー
開発サーバー
© historia Inc. #UE4DD
パッケージ生成
© historia Inc. #UE4DD
UE4 Solution
UE4 Project
Game Project
UE4 では同一プロジェクトから各種パッケージを生成
• Windows Client
• Windows Server
• PS4 Client
• Linux Server
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 Server ビルド
• サーバー上でテスト
• エディタで開発
• Windows Client ビルド
• Windows Server ビルド
• ローカルテスト
Linux クロスコンパイル未使用時
Windows
開発マシン
Linux
開発サーバー
デプロイ
© historia Inc. #UE4DD
• Linux Server ビルド
• サーバー上でテスト
• エディタで開発
• Windows Client ビルド
• Windows Server ビルド
• ローカルテスト
Linux クロスコンパイル未使用時
Windows
開発マシン
Linux
開発サーバー
デプロイ
ビルドエラーで手戻りの可能性!
© historia Inc. #UE4DD
• サーバー上でテスト• エディタで開発
• Windows Client ビルド
• Windows Server ビルド
• ローカルテスト
• Linux Server ビルド
Linux クロスコンパイル使用時
Windows
開発マシン
Linux
開発サーバー
デプロイ
デプロイ先でのエラーを防ぐ
© historia Inc. #UE4DD
https://docs.unrealengine.com/latest/JPN/Platforms/Linux/GettingStarted/index.html