© 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
© historia Inc. #UE4DD
Linux クロスコンパイル時の注意点
 基本的には使用するUE4のバージョンに合わせたツールチェーンのダウンロードと、
環境変数の設定のみ
 複数のUE4プロジェクトが混在していて環境変数を汚染したくない場合、
LINUX_MULTIARCH_ROOT を検索して置き換えることで対応は可能
(DedicatedServer を選択する以上、自ずとエンジンはソースコードビルドになるので・・・)
© historia Inc. #UE4DD
まとめ
 MO ゲーム制作のための機能は一通り揃っている印象
 ただしブラックボックスな部分が多く、実はできるのに知られていない機能や
ini 設定、コンソールコマンドが用意されていたりする
 実際の運用時には NetworkProfiler で細かく使用帯域を見ていく必要がある

UE4 MultiPlayer Online Deep Dive 基礎編1 -Getting Started- (historia様ご講演) #UE4DD

  • 1.
    © historia Inc.#UE4DD Multiplayer Online Deep Dive - Getting Started - historia Inc. 原 龍
  • 2.
    © historia Inc.#UE4DD https://github.com/HogeTatu/UE4Plugin_WebApi
  • 3.
    © historia Inc.#UE4DD 本日の Deep Dive のお題目 Multiplayer Online
  • 4.
    © historia Inc.#UE4DD Multiplayer Online (MO) 人数 少人数(多くても30人程度) プレイ時間 短い(長くても60分程度) 求められるもの リアルタイム性が高い(低レイテンシ) ゲームデザイン • アクション • 格闘ゲーム • FPS, TPS • MOBA (Multiplayer Online Battle Arena)
  • 5.
    © historia Inc.#UE4DD 本日の流れ TravelingDedicated Server RPC / Replicate 導入(オンライン機能概要) はじめに、機能概要と Traveling 周りをヒストリアからご説明 TCP Plugin
  • 6.
    © historia Inc.#UE4DD 本日の流れ TravelingDedicated Server RPC / Replicate 導入(オンライン機能概要) RPC / Replicate を中心に、バイキング様からご説明 TCP Plugin
  • 7.
    © historia Inc.#UE4DD 本日の流れ TravelingDedicated Server RPC / Replicate 導入(オンライン機能概要) Dedicated Server を中心に、ソレイユ様からご説明 TCP Plugin
  • 8.
    © historia Inc.#UE4DD http://cedric-neukirchen.net/Downloads/Compendium/UE4_Network_Compendium_by_Cedric_eXi_Neukirchen.pdf 本日の内容は Cedric ‘eXi’ Neukirchen 様の資料を参考にさせて頂いています。 こちらも合わせてご確認頂けると、理解が進むと思われます。
  • 9.
    © historia Inc.#UE4DD ネットワークモード
  • 10.
    © historia Inc.#UE4DD UE4 は Client-Server (C/S) モデル Client 1 Server Client 2 Client 3 ゲームプレイフローを制御
  • 11.
    © historia Inc.#UE4DD Listen Server (プレイヤーの1人がサーバーを担当) Client 1 Server Client 2 Client 3
  • 12.
    © historia Inc.#UE4DD Dedicated Server (専用のインスタンスがサーバーを担当) Client 1 Client 2 Client 3 Client 4 Server
  • 13.
    © historia Inc.#UE4DD 同期処理 1. Replicate (プロパティ同期)
  • 14.
    © 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); }
  • 15.
    © historia Inc.#UE4DD Actor のプロパティを C/S 間で同期 Blueprint
  • 16.
    © historia Inc.#UE4DD Actor のプロパティを C/S 間で同期後、コールバック通知 C++ /** 同期するプロパティ */ UPROPERTY(ReplicatedUsing=OnRep_SampleProperty) int32 SampleProperty; /** プロパティ同期通知コールバック */ UFUNCTION() void OnRep_SampleProperty(); ※ GetLifetimeReplicatedProps はコールバックの有無で変更なし
  • 17.
    © historia Inc.#UE4DD Actor のプロパティを C/S 間で同期後、コールバック通知 Blueprint
  • 18.
    © historia Inc.#UE4DD Actor Channel ?  C/S 間で Actor と SubObject を同期するための通信チャンネル  Actor のスポーン情報を持ち、レプリケートされた Actor の生成 / 破棄を管理する  所有する FObjectReplicator がプロパティ同期と RPC を行う
  • 19.
    © historia Inc.#UE4DD Server Client Actor Actor Channel Actor Actor Channel • プロパティの差分抽出 • リクエストされた RPC • アクターの生成 • プロパティの反映 • RPC の実行 Actor がレプリケートされる流れ
  • 20.
    © historia Inc.#UE4DD GetLifetimeReplicatedProps の役割  FObjectReplicator がパケットレイアウトを決めるために、 同期するプロパティを判断する際に利用される  同期するプロパティを設定しつつ、同期される条件(≒タイミング)を 指定することも可能
  • 21.
    © 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); }
  • 22.
    © historia Inc.#UE4DD Actor のプロパティを同期する条件を指定 Blueprint
  • 23.
    © 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 リプレイ時以外
  • 24.
    © historia Inc.#UE4DD COND_Custom C++ /** PreReplication で同期する条件を指定 */ void ASampleActor::PreReplication( IRepChangedPropertyTracker& ChangedPropertyTracker) { Super::PreReplication(ChangedPropertyTracker); DOREPLIFETIME_ACTIVE_OVERRIDE( ASampleActor, SampleProp, bReplicateSampleProp); }
  • 25.
    © historia Inc.#UE4DD 同期処理 2. RPC (Remote Procedure Call)
  • 26.
    © historia Inc.#UE4DD Multicast (Server / 全 Client で実行) C++ /** Multicast */ UFUNCTION(NetMulticast, unreliable) void Multicast_SampleEvent(); void ASampleActor::Multicast_SampleEvent_Implementation() { }
  • 27.
    © historia Inc.#UE4DD Multicast (Server / 全 Client で実行) Blueprint
  • 28.
    © 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() { }
  • 29.
    © historia Inc.#UE4DD Run on Owning Client (Actor を所有する Client で実行) Blueprint
  • 30.
    © 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; }
  • 31.
    © historia Inc.#UE4DD Run on Server (Server で実行) Blueprint
  • 32.
    © historia Inc.#UE4DD WithValidation  RPC で呼び出される関数を実行する直前に検証用の関数を実行する  関数名は RPCFunctionName_Validate で戻り値は boolean  戻り値で false を返すと RPC で呼び出された関数は実行されない
  • 33.
    © historia Inc.#UE4DD Reliable  RPC は UDP で通信する都合上、パケットの欠損や順序が不定になるといった ことが起こるため、確実に受信されてほしい処理には向いていない  Reliable フラグを利用することで RPC 実行時に疎通確認を行い、 通信の信頼性を向上させる ことができる
  • 34.
    © historia Inc.#UE4DD Reliable C++ /** Run on Server */ UFUNCTION(Client, reliable, WithValidation) void Server_SampleEvent(); Blueprint
  • 35.
    © historia Inc.#UE4DD Actor の所有権
  • 36.
    © historia Inc.#UE4DD ここはUE4のマルチプレイを理解する上で重要な部分です (ハマりやすい部分です)
  • 37.
    © historia Inc.#UE4DD Actor の所有権とは  Server / Client は Actor に対して所有権を持つ  AActor::Owner で所有権を持つかどうかを判断できる  ただし Pawn の場合は APawn::IsLocallyControlled で判断する  所有権の有無によって、RPCの実行が制限されるケース が存在する
  • 38.
    © historia Inc.#UE4DD RPCの実行が制限されるケース (Server で実行した場合) Actor 所有者 Multicast Run on Server Run on Owning Client Client Server / 全 Client で実行 Server で実行 所有する Client で実行 Server Server / 全 Client で実行 Server で実行 Server で実行
  • 39.
    © historia Inc.#UE4DD RPCの実行が制限されるケース (Client で実行した場合) Actor 所有者 Multicast Run on Server Run on Owning Client 自 Client 自 Client で実行 Server で実行 自 Client で実行 他 Client 自 Client で実行 実行されない 自 Client で実行 Server 自 Client で実行 実行されない 自 Client で実行
  • 40.
    © historia Inc.#UE4DD RPC が実行されないケース – (1) Server Client 1 Client 2 Server が所有する Actor RPC 呼び出し
  • 41.
    © historia Inc.#UE4DD RPC が実行されないケース – (2) Server Client 1 Client 2 他 Client が所有する Actor RPC 呼び出し
  • 42.
    © historia Inc.#UE4DD なぜ所有権は必要? 所有者以外が悪意を持って 不正に Actor を操作する事への対処
  • 43.
    © historia Inc.#UE4DD 所有権によるカテゴライズ  Actor は全ての Server / Client にレプリケートされるわけではい  Actor がどこにレプリケートされるかというカテゴライズは、 Actor のプロパティ設定を元に行われる
  • 44.
    © historia Inc.#UE4DD Client 1 Client 2 Server Only Server  サーバーのみに生成されるアクター  GameMode など
  • 45.
    © historia Inc.#UE4DD Server Only AServerOnlyActor::AServerOnlyActor() { // プレイヤーが持つコントロール権 Role = ROLE_Authority; // 他プレイヤーが持つコントロール権 RemoteRole = ROLE_None; // 同期対象フラグ bReplicates = false; // 所有権を持つクライアントのみに同期するフラグ bOnlyRelevantToOwner = false; }
  • 46.
    © historia Inc.#UE4DD Server  サーバーと全てのクライアントに 生成されるアクター  GameState, PlayerState など  ほとんどのアクターはこの設定で サーバーが生成し、レプリケートされる Server & Client Client 1 Client 2
  • 47.
    © historia Inc.#UE4DD AServerClientActor::AServerClientActor() { // プレイヤーが持つコントロール権 Role = ROLE_Authority; // 他プレイヤーが持つコントロール権 RemoteRole = ROLE_SimulatedProxy; // 同期対象フラグ bReplicates = true; // 所有権を持つクライアントのみに同期するフラグ bOnlyRelevantToOwner = false; } Server & Client
  • 48.
    © historia Inc.#UE4DD Server  サーバーと所有するクライアントのみに 生成されるアクター  PlayerController, Possess している Pawn など Client 1 Client 2 Server & Client (所有者)
  • 49.
    © historia Inc.#UE4DD AServerOwningClientActor::AServerOwningClientActor() { // プレイヤーが持つコントロール権 Role = ROLE_Authority; // 他プレイヤーが持つコントロール権 RemoteRole = ROLE_SimulatedProxy; // 同期対象フラグ bReplicates = true; // 所有権を持つクライアントのみに同期するフラグ bOnlyRelevantToOwner = true; } Server & Client (所有者)
  • 50.
    © historia Inc.#UE4DD OnlineSubsystem
  • 51.
    © historia Inc.#UE4DD ゲーム OnlineSubsystem • ログイン • セッション管理 • マッチング • 実績 • ランキング • チャット • ストア(課金) etc... Steam PS4 Oculus Google Amazon Facebook プラットフォームの APIを抽象化 各種SDK
  • 52.
    © historia Inc.#UE4DD OnlineSubsystem の設計  各プラットフォームは機能別に定義されたインターフェースを継承したクラスを実装する  インターフェースは IOnline[機能名] で用意されている – ex. IOnlineAchievements  各プラットフォームは FOnline[機能名][プラットフォーム名] で実装する – ex. FOnlineAchievementSteam
  • 53.
    © historia Inc.#UE4DD OnlineSubsystem で機能が足りていなかった場合は?  必要なインターフェースを継承しつつ、足りていない機能のクラスを新規作成する  IOnlineSubsystem を継承しながら、プラットフォーム別に FOnlineSubsystem[プラットフォーム] が実装されているので、 各機能の実装を取得する Get[機能名]Interface で追加した機能の リファレンスを返すようにする
  • 54.
  • 55.
    © historia Inc.#UE4DD ここからは開発フローについて
  • 56.
    © historia Inc.#UE4DD Release QADevelopment ネットワーク対応ゲームの基本的なデプロイフロー 作業PC 開発サーバー ステージング サーバー 公開サーバー
  • 57.
    © historia Inc.#UE4DD Release QADevelopment 作業PC 開発サーバー ステージング サーバー 公開サーバー 作業PC(ローカル)
  • 58.
    © historia Inc.#UE4DD ローカルでのマルチプレイプレビュー 1. PIE 起動
  • 59.
  • 60.
  • 61.
    © historia Inc.#UE4DD PIE 起動時に自動でマッチングされた状態にする Editor Preferences -> Level Editor -> Play -> Multiplayer Options -> Auto Connect To Server 単体のレベルでマルチプレイのデバッグを行うときに有効
  • 62.
    © historia Inc.#UE4DD Auto Connect To Server の注意点  簡易的に Server / Client の設定だけ行ってプレビューを行っている  つまり C/S 間で正式な手続き(Control Channel でのメッセージング) を行っていないため、レベル移動を行ってしまうと正常な結果にならない
  • 63.
    © historia Inc.#UE4DD ローカルでのマルチプレイプレビュー 2. –game オプションで起動
  • 64.
    © historia Inc.#UE4DD UE4Editor.exe に uproject を指定して -game オプションを付けて起動すると、 Cook 無しスタンドアロン実行 が可能
  • 65.
    © 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 起動バッチを作ると便利
  • 66.
  • 67.
    © historia Inc.#UE4DD PIE 起動でのプレビューはあくまで単一プロセスでの実行で ダミー的に処理されている部分があるため、 デプロイ前には一度デバッグしておいた方が良い
  • 68.
    © historia Inc.#UE4DD パケットシミュレーション
  • 69.
    © historia Inc.#UE4DD ローカルプレビューではパケットの遅延等が全く発生せず、 実際にマシン間で通信する際に 意図した挙動にならないといった事が起こりえます
  • 70.
    © historia Inc.#UE4DD ローカルプレビュー時にこのような状態を再現するため、 エミュレート用の各種デバッグコマンドが用意されています
  • 71.
    © historia Inc.#UE4DD Net PktLoss=[Int]  確率でパケットを送信しない(消失シミュレーション)  単位は 0 – 100 %
  • 72.
    © historia Inc.#UE4DD Net PktOrder=[Boolean]  パケットをバッファリングして送信順序をランダムにする  単位は 0 – 1
  • 73.
    © historia Inc.#UE4DD Net PktLag=[Int]  パケット送信時に遅延を発生させる(固定値)  単位はミリ秒
  • 74.
    © historia Inc.#UE4DD Net PktLagVariance=[Int]  パケット送信時に遅延を発生させる(範囲ランダム値)  単位は ± ミリ秒
  • 75.
    © historia Inc.#UE4DD B.SendTime = FPlatformTime::Seconds() + (double(PacketSimulationSettings.PktLag) + 2.0f * (FMath::FRand() - 0.5f) * double(PacketSimulationSettings.PktLagVariance))/ 1000.f;
  • 76.
    © historia Inc.#UE4DD Net PktDup=[Int]  パケット送信時に確率で2回送信する(重複させる)  単位は 0 – 100 %
  • 77.
    © historia Inc.#UE4DD この辺の実装は UNetConnection::FlushNet
  • 78.
    © historia Inc.#UE4DD RPC のデバッグ
  • 79.
    © historia Inc.#UE4DD net.RPC.Debug [Boolean] RPC 実行時のログを Warning で出力する 有効にした状態で LogNet でフィルターを設定すると Traveling や Replicate の流れがよく見える
  • 80.
    © historia Inc.#UE4DD ネットワークプロファイラ
  • 81.
    © historia Inc.#UE4DD ネットワークプロファイラ  Replication, RPC に関するプロファイラ  帯域のボトルネックを調査する時に有用  Actor / Property / RPC でフィルタリングすることも可能
  • 82.
    © historia Inc.#UE4DD ネットワークプロファイラ  netprofile enable/disable でプロファイリング状態を切り替える  プロファイリング結果を確認するためには下記パスからツールを起動する – /Engine/Binaries/DotNET/NetworkProfiler.exe  プロファイリング結果は下記ディレクトリに保存されている – /ProjectRoot/Saved/Profiling
  • 83.
  • 84.
    © historia Inc.#UE4DD https://docs.unrealengine.com/latest/JPN/Gameplay/Tools/NetworkProfiler/index.html
  • 85.
    © historia Inc.#UE4DD Release QADevelopment 作業PC 開発サーバー ステージング サーバー 公開サーバー 開発サーバー
  • 86.
    © historia Inc.#UE4DD パッケージ生成
  • 87.
    © historia Inc.#UE4DD UE4 Solution UE4 Project Game Project UE4 では同一プロジェクトから各種パッケージを生成 • Windows Client • Windows Server • PS4 Client • Linux Server etc ...
  • 88.
    © historia Inc.#UE4DD Build Configuration ビルド名 ビルド概要 ビルドルールを指定するファイル [empty] スタンドアロンゲーム実行用のビルド ProjectName.Target.cs Editor エディタ実行用のビルド ProjectNameEditor.Target.cs Client マルチプレイゲームにおけるクライアント用のビルド ProjectNameClient.Target.cs Server マルチプレイゲームにおけるサーバー用のビルド ProjectNameServer.Target.cs
  • 89.
  • 90.
  • 91.
    © historia Inc.#UE4DD ビルドジョブセットからまとめて各種ビルドを実行する Batch Builder (UnrealVS 拡張) が便利
  • 92.
    © historia Inc.#UE4DD Batch Builder はこのボタンから起動する
  • 93.
    © historia Inc.#UE4DD https://docs.unrealengine.com/latest/JPN/Programming/Development/VisualStudioSetup/UnrealVS/index.html
  • 94.
    © historia Inc.#UE4DD Client / Server ビルドで謎のコンパイルエラーが…? Client / Server ビルドは、ランチャーからインストールしたエンジンだとビルドできない仕様 (ProjectName.sln ではなく、UE4.sln からのみビルド可能)
  • 95.
    © historia Inc.#UE4DD Cook は ProjectLauncher から行うと 複数パッケージを同時に生成できる
  • 96.
    © historia Inc.#UE4DD Linux クロスコンパイル
  • 97.
    © historia Inc.#UE4DD • Linux Server ビルド • サーバー上でテスト • エディタで開発 • Windows Client ビルド • Windows Server ビルド • ローカルテスト Linux クロスコンパイル未使用時 Windows 開発マシン Linux 開発サーバー デプロイ
  • 98.
    © historia Inc.#UE4DD • Linux Server ビルド • サーバー上でテスト • エディタで開発 • Windows Client ビルド • Windows Server ビルド • ローカルテスト Linux クロスコンパイル未使用時 Windows 開発マシン Linux 開発サーバー デプロイ ビルドエラーで手戻りの可能性!
  • 99.
    © historia Inc.#UE4DD • サーバー上でテスト• エディタで開発 • Windows Client ビルド • Windows Server ビルド • ローカルテスト • Linux Server ビルド Linux クロスコンパイル使用時 Windows 開発マシン Linux 開発サーバー デプロイ デプロイ先でのエラーを防ぐ
  • 100.
    © historia Inc.#UE4DD https://docs.unrealengine.com/latest/JPN/Platforms/Linux/GettingStarted/index.html
  • 101.
    © historia Inc.#UE4DD Linux クロスコンパイル時の注意点  基本的には使用するUE4のバージョンに合わせたツールチェーンのダウンロードと、 環境変数の設定のみ  複数のUE4プロジェクトが混在していて環境変数を汚染したくない場合、 LINUX_MULTIARCH_ROOT を検索して置き換えることで対応は可能 (DedicatedServer を選択する以上、自ずとエンジンはソースコードビルドになるので・・・)
  • 102.
    © historia Inc.#UE4DD まとめ  MO ゲーム制作のための機能は一通り揃っている印象  ただしブラックボックスな部分が多く、実はできるのに知られていない機能や ini 設定、コンソールコマンドが用意されていたりする  実際の運用時には NetworkProfiler で細かく使用帯域を見ていく必要がある