UE4でマルチプレイヤーゲームを作ろう【CEDEC 2019】

273.9K Views

September 30, 19

スライド概要

2019年9月6日に行われた「CEDEC2019」で登壇した際に使用した資料です。

profile-image

Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

UE4でマルチプレイゲームをつくろう Epic Games Japan Support Engineer Takashi Suzuki V1.0 Sep 2019

2.

自己紹介 エピックゲームズジャパン サポートエンジニア 鈴木孝司 2019年6月から現職 アーケード向け、家庭用、VR向けなどいろいろなゲームを 作ってきました UnrealEngineは無料化直後から触っています #UE4 | @UNREALENGINE

3.

マルチプレイヤーゲーム 楽しんでますか? #UE4 | @UNREALENGINE

4.

昨今は様々なマルチプレイ対応ゲームが リリースされ、 老若男女地域を問わず楽しまれています #UE4 | @UNREALENGINE

5.

Fortniteも 絶賛サービス中です #UE4 | @UNREALENGINE

6.

eSportsにとっても マルチプレイは 重要な要素です #UE4 | @UNREALENGINE

7.

マルチプレイは楽しい #UE4 | @UNREALENGINE

8.

UE4を使えば ある程度エンジンが 面倒を見てくれます #UE4 | @UNREALENGINE

9.

実際に作ってみると #UE4 | @UNREALENGINE

10.

一人用ゲームでは起きない様々な問題が ローカルでは動いたのに、いざマルチで実際に動かしたら上手く動かない こっちではドアが開いてるのに、あっちでは開いてない ラグい!!! このタイミングで接続/切断されるとバグる どこまでテストすればいいの? 再生されるモーションが違うんですが・・・ #UE4 | @UNREALENGINE

11.

ソロゲームのX倍 テストや実装コストが かかります #UE4 | @UNREALENGINE

12.

ネットワーク通信帯域は 有限です #UE4 | @UNREALENGINE

13.

トラブルや疑問が あったときの技術情報も 見つけにくい気がします #UE4 | @UNREALENGINE

14.

正しい情報、問題点、 セオリーがわかれば かなり負担を軽減できます #UE4 | @UNREALENGINE

15.

本講演の目標 #UE4 | @UNREALENGINE

16.

みなさまが 楽しいマルチプレイゲームを もっと楽しく 作ってもらえるようにする #UE4 | @UNREALENGINE

17.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

18.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

19.

学習用リソース UE4にはエンジンに組み込まれた マルチプレイヤー用の機能が あります。 マルチプレイ可能なテンプレートプ ロジェクトやサンプルプロジェクト でそれらについてを学習することが できます。 #UE4 | @UNREALENGINE

20.

はじめに ちょっとだけボリュームが多くなってしまったので、 発展的なトピックや詳細に関してはざっと流して進みます スライドはCEDILやSlideShareなどで公開いたしますので、公開後に目を通して 頂けると幸いです スライド中にこのような暗い色の文章がありますが、 公開スライドは明るく調整したものを用意します 中辛 #UE4 | @UNREALENGINE 辛口 激辛

21.

実際触れるサンプル紹介 #UE4 | @UNREALENGINE

22.

ThirdPersonテンプレート #UE4 | @UNREALENGINE

23.

Vehicle Advanced テンプレート Net PktLag=200を設定した状態 #UE4 | @UNREALENGINE

24.

他のテンプレートも マルチプレイ対応のものが 多いです #UE4 | @UNREALENGINE

25.

機能別サンプル ( Contents Example ) #UE4 | @UNREALENGINE

26.

#UE4 | @UNREALENGINE

27.

ShooterGame #UE4 | @UNREALENGINE

28.

ドキュメント ⚫ UE4公式ドキュメント ⚫ https://docs.unrealengine.com/jp/index.html ⚫ http://cedric-neukirchen.net/Downloads/Compendium/UE4_Network_Compendium_by_Cedric_eXi_Neukirchen.pdf ⚫ ⚫ https://wiki.unrealengine.com/index.php?title=Main_Page ⚫ 'Unreal Engine 4' Network Compendium ⚫ EpicWiki ⚫ ⚫ DedicatedServerGuide ⚫ https://wiki.unrealengine.com/index.php?title=Dedicated_Server_Guide_(Windows_%26_Linux) 他多数 ⚫ https://www.slideshare.net/EpicGamesJapan/online-multiplay-game-design SlideShare #UE4 | @UNREALENGINE

29.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

30.

機能 ウォークスルー #UE4 | @UNREALENGINE UE4にはどんな機能が組み込 まれているか見てみましょう

31.

エンジンに統合された通信機能 アクターやブループリントといった エンジンの基本的なしくみは すべてネットワークに対応しています 特殊な処理を除き、大半を ブループリントを用いて ネットワーク対応のタイトルを 開発することができます #UE4 | @UNREALENGINE

32.

サーバークライアントモデル UE4が提供するネットワークの構造はサーバークライアントモデルです サーバー権限を持ったプロセスは一つです #UE4 | @UNREALENGINE

33.

大まかに 二つの実現方法があります #UE4 | @UNREALENGINE

34.

兼業サーバー - ListenServer #UE4 | @UNREALENGINE

35.

兼業サーバー - ListenServer プレイヤーの誰かがサーバーを兼ねる方法 コンソールゲームでよく利用されます ⚫ メリット ⚫ サーバーの維持費がかからない ⚫ ⚫ ⚫ ⚫ サーバー役のCPU/通信負荷が高く、通信品質が求められる サーバー役とクライアントで有利不利の差がどうしても出てしまう サーバー役がいなくなると解散になってしまう NAT問題(いわゆるルーター越え問題) ⚫ デメリット #UE4 | @UNREALENGINE

36.

専業サーバー - DedicatedServer #UE4 | @UNREALENGINE

37.

専業サーバー - DedicatedServer 余計なものを削ぎ落した専用サーバーを、コンピューターに配置して実行します 製品版ではデータセンターに配置されます プレイヤーはすべてクライアントとして接続されます ⚫ メリット ⚫ ⚫ ⚫ ⚫ グラフィックスやサウンドなどの処理を省けるので負荷が低い NATの問題が無く、通信障害などが無い限り接続に成功する プレイヤー間の優劣が無い データセンターへの経路はよく調整されており通信品質が期待できる ⚫ 運用コストがかかる ⚫ デメリット #UE4 | @UNREALENGINE

38.

OnlineSubsystem プラットフォームが提供するマッチングやリーダーボードなどの機能を 抽象化して制御できるようにする仕組みです。 #UE4 | @UNREALENGINE

39.

リプレイ UE4が提供するリプレイ機能はマルチプレイでやりとりされている パケットデータをストレージに記録して、後でそれを再生する仕組みです。 #UE4 | @UNREALENGINE

40.

NetworkProfiler [InstallFolder]¥Engine¥Binaries¥DotNET¥NetworkProfiler.exe #UE4 | @UNREALENGINE

41.

NetworkProfilerでキャプチャする ConsoleCommand netprofileでON/OFFを切り替える netprofile CommandLineOption MyProjServer.exe -networkprofiler=true -log #UE4 | @UNREALENGINE

42.

エンジンが提供する 枠組みとしては こんな感じです #UE4 | @UNREALENGINE

43.

DedicatedServerの 話が出たのでちょっと脇道 #UE4 | @UNREALENGINE

44.

DedicatedServerのホスティング Dedicatedサーバーを検討する時はサーバー数をユーザーの要求に合わせて 自動で増減させること(オートスケーリング)を検討してください 弊社Fortniteも社内開発のオートスケーリングシステムをもちいて サーバーをクラウド上で管理運営しています #UE4 | @UNREALENGINE

45.

オートスケーリングソリューション #UE4 | @UNREALENGINE

46.

DedicatedServerの運用コストTIPS 一つのVMインスタンス上にCPUやメモリ、ネットワーク帯域/パケット数が許す 限り複数のサーバープロセスを起動させる事が可能です CPUの使用率とパケット数はサーバーのフレームレートに 大きく影響を受けます。 クライアントとサーバーのフレームレートは一致している必要は無いのでゲーム に影響が無い範囲でフレームレートを絞るとコスト的に有利です。 Engine.ini NetServerMaxTickRate=30 60FPSクライアント 20FPSサーバー 30FPSクライアント #UE4 | @UNREALENGINE

47.

DedicatedServerの作り方 RunUATやBuildGraphなどを使ってビルドすることができます ビルドの前にサーバー用のターゲットスクリプトを確認してください UATを使う場合は以下の様に serverオプションとサーバー用の設定を渡します RunUAT BuildCookRun -project=W:/workspace/MyProj/MyProj.uproject -noP4 -ue4exe=UE4Editor-Cmd.exe -targetplatform=Win64 -clientconfig=Development -noclient -serverplatform=Win64 -serverconfig=Development+Shipping -server -compile -build -cook -compressed -stage -package -pak -nocompileeditor -utf8output 参考ページ→ #UE4 | @UNREALENGINE https://wiki.unrealengine.com/Dedicated_Server_Guide_(Windows_%26_Linux)

48.

【参考】 Epic Online Service (EOS) #UE4 | @UNREALENGINE

49.

Epic Online Service Unreal Engine とは別にエピックゲームズが提供している ゲームサーバーサービス ● 特徴 ● 一般的にプラットフォーム向けのSDKが提供している、マッチング、ユーザー管理、分析、 ランキングなどのサービスをプラットフォームに依存しない形(クロスプラットフォーム)で 提供し、無料で利用できます ● 現在提供されている機能はまだ一部で、鋭意開発中です ● オープンソースソフトウェアではありません ● このサービスを利用するに当たって、UE4を使う必要はありません 他のゲームエンジンやミドルウェアを使用しないタイトルでも問題無く利用可能です ● サーバーは弊社が管理しており、この利用料も発生しません ● DedicatedServerのホスティングは含まれません ● 詳しくはEOSのポータルをご覧ください ● https://dev.epicgames.com/ja/services #UE4 | @UNREALENGINE

50.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

51.

ThirdPersonTemplateで 動作検証方法 #UE4 | @UNREALENGINE 新規プロジェクトを 作った場合を見てみます

52.

#UE4 | @UNREALENGINE

53.

かんたん! #UE4 | @UNREALENGINE

54.

Play In Editor (PIE) エディタ上でメモリに読み込まれているアセットを 利用できるので、素早くマルチプレイでのレベルを 確認するのに有効です。 エディタのプロセス上で指定した分のプレイヤー (+DedicatedServer)のワールドを複数生成し 直列に処理します。 ※UseSingleProcess : ON 時 #UE4 | @UNREALENGINE

55.

New Editor Window 実行の注意点 ⚫ シームレストラベルは無視されます ⚫ ウィンドウを閉じるとすべてのセッションが終わります ⚫ Statsファイルやカウンタがすべてのクライアント分まとまってしまいます #UE4 | @UNREALENGINE

56.

シームレストラベルの 動作確認 ※「シームレストラベル」とは通信を維持したまま スムーズにレベルを遷移するUE4の仕組みです #UE4 | @UNREALENGINE

57.

#UE4 | @UNREALENGINE

58.

SeamlessTravelはPIE非対応 #UE4 | @UNREALENGINE

59.

大丈夫! 確認方法があります! Use Single Process : OFF #UE4 | @UNREALENGINE

60.

#UE4 | @UNREALENGINE

61.

Use Single Process OFF 一つのクライアントをPIEで起動し、残りをStandaloneで起動します PIEで起動する一つをクライアントして立ち上げるかサーバーとして立ち上げるか を選択するのがEditorMultiplayerModeです。 PIEで起動しているクライアントはブループリントのデバッグが可能です #UE4 | @UNREALENGINE

62.

任意タイミングの ログイン検証 #UE4 | @UNREALENGINE

63.

#UE4 | @UNREALENGINE

64.

Auto Connect To Server OFF NewEditorWindow では、 指定したプレイヤー数分、ネットワーク非接続の状態 でクライアントが起動します。以下の手順でログインのテストが可能です。 1.サーバーになるウィンドウで?listen オプション付きでレベル移動 open ?listen または open ThirdPersonExample?listen 2.クライアントウィンドウで open 127.0.0.1 と入力しサーバーに接続 open 127.0.0.1 #UE4 | @UNREALENGINE

65.

Standalone起動 #UE4 | @UNREALENGINE

66.

Standalone起動 注意点! EditorMultiplayerModeが 「Play Offline」だと強制シングルプレイ になってしまいます UseSingleProcessのチェックを外して Play Offline以外に変更してください #UE4 | @UNREALENGINE

67.

Standalone起動でのマルチプレイ確認 複数のプロセスを立ち上げてパッケージビルドに近い形でテストが可能です SeamlessTravelなども確認可能です AutoConnectServerオプションやUseDedicatedServerなどにも対応しています サーバーのポートはAdvancedOption内で指定したものが使われるので (デフォルトで 17777)、任意の接続を試したい場合は Open 127.0.01:17777 などでポートを指定して接続します 欠点としては開発PCのメモリやCPUのリソースを大量に消費することと、 それに関連して起動が遅いことです。 #UE4 | @UNREALENGINE

68.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

69.

ネット処理の流れと 用語集 #UE4 | @UNREALENGINE

70.

まず1Tickの中で ネットワークがどう処理され ているのか見てみます #UE4 | @UNREALENGINE

71.

Tickのながれ 受信して配達 インターネット ゲームの更新! 情報を集める #UE4 | @UNREALENGINE 送信!

72.

文字で起こしてみる 1. UWorld::Tick 1. UNetworkDriver::TickDispatch 1. Packet受信 > Bunchに分解 1. BunchをActorChannelに流して、プロパティをレプリケート+RPCの実行 2. PostReceivedBunch > RepNotifyを処理 2. タスクグラフのループ 1. RPCの呼び出し (ServerMoveなど) 3. UNetworkDriver::TickFlush 1. BuildConsiderList 考慮するべきNetActorのリストを作る 2. Connection毎のループ 1. PrioritizeActors 2. ProcessePrioritizedActors 1. ActorChannel毎にプロパティの差分を抽出してBunchを書き出す 3. Connection毎のループ - UNetConnection::Tick 1. UNetConnection::FlushNet() こちらもお勧め https://docs.unrealengine.com/ja/Gameplay/Networking/Actors/ReplicationFlow/index.html #UE4 | @UNREALENGINE

73.

はじめましての 単語が多くて辛い! #UE4 | @UNREALENGINE

74.

単語解説 ・・・というわけで マルチプレイヤーゲームを作成する 上で遭遇する謎の単語達をすこし掘 り込んで解説していきます 各単語の意味を理解することでより 適切な設計を行えるようになります #UE4 | @UNREALENGINE Actor編 NetworkDriver編

75.

単語解説 Actor編 NetworkDriver編 #UE4 | @UNREALENGINE

76.

Actor #UE4 | @UNREALENGINE

77.

Actor UE4の基本的なオブジェクト レプリケーション(状態の複製)は このActor単位で行われます これらのうちbReplicateフラグが 立っているものがエンジンによって 複製の対象として処理されます #UE4 | @UNREALENGINE

78.

レプリケートフラグ ONで サーバーからクライアントに アクターが複製されます #UE4 | @UNREALENGINE

79.

双方向には 同期されていないことに注意 #UE4 | @UNREALENGINE

80.

#UE4 | @UNREALENGINE

81.

bReplicatesフラグの動的切り替え レプリケーションのフラグは 実行中に切り替える事が可能です ● False -> True に切り替えた場合 ● リストに登録されて、クライアント上に複製されていなかった アクターがクライアント上に登場します ● True -> False に切り替えた場合 ● リストから削除されてレプリケート対象から除外され CPU負荷と帯域負荷を軽減できます ● 生成されてしまったアクターチャンネルはそのまま維持されます ● 一度複製されたクライアント上のキャラクターは消えません! ● アクターが破壊された時にレプリケーションフラグが落ちていたとしても ActorChannelの破壊に連動してクライアント上でもアクターは破壊されます #UE4 | @UNREALENGINE

82.

Server Client サーバー クライアント 3秒ごとにフラグ切り替え 15秒後に破壊 TimeはGetGameTImeSinceCreationの値 #UE4 | @UNREALENGINE

83.

アクターを削除するときは サーバー上で消せばOK #UE4 | @UNREALENGINE

84.

Role #UE4 | @UNREALENGINE

85.

役割は大雑把に3種類 #UE4 | @UNREALENGINE

86.

Authority(権利者) 超えらい 会社でいうと社長 サーバー上に居て いろんな事を 言ってくる これはイメージです(強調) #UE4 | @UNREALENGINE

87.

AutonomousProxy(自立代理人) ちょっと裁量権がある 会社でいうと係長 社長にすこし モノ言うことができる グレイマン係長 #UE4 | @UNREALENGINE

88.

SimulateProxy(したっぱ) 裁量権が無く 社長の言う通り動く 会社でいうと社員 社長に直接なにかを 進言することはできない 写真はイメージです #UE4 | @UNREALENGINE

89.

サーバー クライアント displayall Pawn Role #UE4 | @UNREALENGINE

90.

サーバー クライアント displayall Pawn Role #UE4 | @UNREALENGINE

91.

PlayerController &Pawn Replicateが設定されて いるActor Replicateが設定されて いない静的なアクター Replicateナシ ローカルで生成 #UE4 | @UNREALENGINE ローカルか否か Server Client Role Authority AutonomousProxy RemoteRole AutonomousProxy Authority Role Authority SimulateProxy RemoteRole SimulateProxy Authority Role Authority None RemoteRole None Authority Role Authority Authority RemoteRole None None

92.

サーバーにバレずに 作ったアクターは クライアントのもの #UE4 | @UNREALENGINE

93.

NetDormancy 休眠状態 #UE4 | @UNREALENGINE

94.

用がない場合は休む #UE4 | @UNREALENGINE

95.

3分 #UE4 | @UNREALENGINE 3分

96.

3分 3分 プロパティが変更されると、 変更情報がクライアントに送信されます 変更がないときは・・・? #UE4 | @UNREALENGINE

97.

要 チ ェ ッ ク や !! 3分 3分 変化していないのに関わらず、 変更がないことを何回も何回もチェックされています #UE4 | @UNREALENGINE

98.

3分 休眠中 #UE4 | @UNREALENGINE 3分 休眠中

99.

休眠状態 NetDormant/NetDormancy サーバー上でAActror::SetNetDormancyなどを利用して休眠状態を設定し、 レプリケーション処理のチェック対象から除外し負荷を軽減する最適化用の機能 実際に休眠状態に入るためには、レプリケートするべきプロパティが無い状態を 作る必要があります。 #UE4 | @UNREALENGINE

100.

休眠状態 NetDormancy 一度休眠状態に入ったアクターはFlushNetDormancy()が呼ばれると 眠りから覚めます この関数ははプロパティの変更などによってエンジンから呼び出されます つまり休眠状態はある程度自動で動作します 一定時間変更が加わらない可能性があるアクターは休眠状態への移行を要求する ことでレプリケーションの処理時間を軽減することができます。 プロパティの変化が激しいアクターに適用すると状態移行チェックの負荷が加わ ってしまうだけになります #UE4 | @UNREALENGINE

101.

休眠状態の設定値 備考 DORM_Never DORM_Awakeと同等 DORM_Awake(Default) 休眠状態なら復帰し休眠状態に入らない。 DORM_DormantAll 休眠状態へのチェックを行い条件を満たせば休眠状態に移行する DORM_DormantPartial Connection毎に挙動を切り替えることができる模様 AActor::GetNetDormancyの実装が必要 DORM_Initial 初期状態でNetActorListから除外され休眠状態に入る FlushNetDormancyが呼ばれるとDORM_DormantAllに移行する #UE4 | @UNREALENGINE

102.

ほとんど変化が無いアクター はDormantAll さらにレベル配置物は Initialがお勧め #UE4 | @UNREALENGINE

103.

NetRelevancy 関係性 #UE4 | @UNREALENGINE

104.

興味がないものは 省いて省エネする #UE4 | @UNREALENGINE

105.

関連性 NetRelevancy サーバー上でConnection毎に距離などを考慮して そのアクターをレプリケートするべきか判断する仕組み。 レプリケーション処理の中では、アクターが列挙されて優先順位別にならんだあ と、実際にプロパティを調べる直前にAActor::IsNetRelevantForを通じてチェッ クされます。 NetActor リスト生成 #UE4 | @UNREALENGINE 優先順位 ソート 関連性チェック 変更差分の取得と 送信

106.

距離カリングとAlwaysRelevant AActor::IsNetRelevantFor()では 距離ベースのカリングが行われます そのパラメータがNetCullDistancSquaredです 225,000,000 cm^2 = 15,000 cm = 150m この距離カリングなどすべて無効にして常にカリ ングされないようにするプロパティが AlwaysRelevantです。 #UE4 | @UNREALENGINE

107.

NetPriority 通信優先度 #UE4 | @UNREALENGINE

108.

限られたパイプに なにを優先して流すか #UE4 | @UNREALENGINE

109.

NetPriority レプリケートされる優先順位を決めるパラメータ 値が高いほど処理列の先頭側にソートされ、 相対的に高頻度でレプリケートされます 実際にソートに使われる値は NetPriority値 × (前回送信時からの経過時間+向きや距離などの係数) 「特定の条件時は、今回のTickの中でパケットに乗るようにしたい」というよう な要求に答える場合は、後述のForceNetUpdateに加えて、NetPriorityを変更す るかAActor::GetNetPriorityをオーバーライドして実現することが可能です #UE4 | @UNREALENGINE

110.

送信! 次のTickに持ち越し Frame 1 Pawn P:4 t:1 = 4 Pawn P:4 t:1 = 4 A P:1 t:4 = 4 B P:1 t:3 = 3 C P:1 t:2 = 2 C P:1 t:1 = 1 Frame 2 Pawn P:4 t:1 = 4 Pawn P:4 t:1 = 4 B P:1 t:4 = 4 C P:1 t:3 = 3 C P:1 t:2 = 2 A P:1 t:1 = 1 Frame 3 Pawn P:4 t:1 = 4 Pawn P:4 t:1 = 4 C P:1 t:4 = 4 C P:1 t:3 = 3 A P:1 t:2 = 2 B P:1 t:1 = 1 Frame 4 Pawn P:4 t:1 = 4 Pawn P:4 t:1 = 4 C P:1 t:4 = 4 A P:1 t:3 = 3 B P:1 t:2 = 2 C P:1 t:1 = 1 #UE4 | @UNREALENGINE

111.

NetUpdateFrequency 送信チェック頻度 #UE4 | @UNREALENGINE

112.

遅れても良いものは 毎Tick送らなくてよいです #UE4 | @UNREALENGINE

113.

サーバー クライアント #UE4 | @UNREALENGINE

114.

NetUpdateFrequency アクターのレプリケーション頻度 単位は 「回/s」 です 一度アクターのレプリケーションが行われると、このパラメータの逆数時間、 レプリケーション考慮リストから除外されます 素早い反応が不要なアクターはこの頻度を下げることで CPUおよび帯域幅を削減可能です 混乱しやすいのですが、AActor::ForceNetUpdateは このインターバル時間をリセットする関数です。 #UE4 | @UNREALENGINE

115.

Min Net Update Frequency とは MinNetUpdateFrequencyは「AdaptiveNetUpdateFrequency」が 有効なときだけ使われるパラメータです この機能はデフォルトでOFFです これは実際にレプリケートされた間隔の 実績値に合わせて、 Min~とNetUpdateFrequencyの間で パラメータを自動調節する機能です #UE4 | @UNREALENGINE

116.

NetLoadOnClient #UE4 | @UNREALENGINE

117.

レベルに 配置されているものを クライアント上で 作るかどうか #UE4 | @UNREALENGINE

118.

NetLoadOnClient レベルに含まれるアクターのうち、クライアント上でアクターをワールドに生成 するかどうかを示すフラグ クライアント上に居てほしくない時にfalseにします 代表的なものはGameModeです NetLoadOnClient bReplicates AGameMode false false ANavigationData false false APlayerState false true AGameState false true #UE4 | @UNREALENGINE クライアント上では生まれない レベル初期化時にクライアント上から削 除され、サーバーからのレプリケーショ ンで複製される

119.

Actor編まとめ ⚫ Actorにはネットワーク上での振る舞いを設定したり、パフォーマンスを調 整するための設定があります ⚫ 重要なのは複製設定を立てることでサーバーからクライアントにアクターが 複製されるということです #UE4 | @UNREALENGINE

120.

単語解説 Actor編 NetworkDriver編 #UE4 | @UNREALENGINE

121.

ここからNetworkDriverと その中身の解説します #UE4 | @UNREALENGINE

122.

NetworkDriver #UE4 | @UNREALENGINE

123.

アンリアル島 #UE4 | @UNREALENGINE

124.

アンリアル島 #UE4 | @UNREALENGINE

125.

アンリアル島 #UE4 | @UNREALENGINE

126.

NetworkDriver ネットワーク処理の大元です。 マルチプレイが要求されると生成されてWorldに紐づけられます クライアントとサーバーの両方がそれぞれNetworkDriverを持ちます #UE4 | @UNREALENGINE

127.

NetConnection #UE4 | @UNREALENGINE

128.

サーバー NetworkDriver NetConnection NetConnection NetConnection NetConnection NetConnection NetConnection NetworkDriver NetworkDriver NetworkDriver クライアントA クライアントB クライアントC #UE4 | @UNREALENGINE

129.

NetConnection NetworkDriverとNetworkDriverをつなぐ経路です クライアントは一つ、サーバーには接続しているプレイヤー数分作られます #UE4 | @UNREALENGINE

130.

PlayerController #UE4 | @UNREALENGINE

131.

リッスンサーバー NetConnection NetConnection NetConnection LocalPlayer NetConnection NetConnection NetConnection クライアントA クライアントB クライアントC #UE4 | @UNREALENGINE

132.

APlayerController サーバーにログインしたときに作られます プロパティとしてPlayerというメンバ変数に NetworkConnectionが設定されて1対1でつながります displayall PlayerController Player #UE4 | @UNREALENGINE

133.

PlayerController Advanced ServerRPCやClientRPCが特定の対象だけに届くのは、 有効なNetConnectionをPlayerプロパティを持っているかどうかです PawnはPlayerControllerに所持(Possess)されている場合のみ所持元の PlayerControllerがもつNetConnectionを使えます ( APawn::GetNetConnection & APlayerController::GetNetConnection 参照 ) #UE4 | @UNREALENGINE

134.

PlayerController RPC GetNetConnection RPC Pawn PlayerController GetNetConnection GetNetConnection NetConnection NetConnection Actor RPC GetNetConnection #UE4 | @UNREALENGINE 送信されない!

135.

NetworkObjectList #UE4 | @UNREALENGINE

136.

アンリアル島 #UE4 | @UNREALENGINE

137.

NetworkObjectList NetworkDriverの中にあるネットワークでやりとりしたいアクターのリスト NetworkObjectInfoはその要素の型。 前述の通信頻度(NetUpdateFrequency)の計算に用いる変数を持っています NetConnection毎にはもっていない事に注意してください #UE4 | @UNREALENGINE

138.

UActorChannel ChannelIndex FNetworkGUID #UE4 | @UNREALENGINE

139.

NetConnection 35番 8番 10番 #UE4 | @UNREALENGINE 35番 8番 10番

140.

35番 35番 8番 8番 ChannelIndex 10番 #UE4 | @UNREALENGINE ActorChannel 10番

141.

ChannelIndexは ActorChannelの 配列番号 #UE4 | @UNREALENGINE

142.

ActorChannelとChannelIndex ActorChannelは複製対象のアクター1つに付き1つ割り当てられる経路 ChannelIndexは静的に確保されているチャンネル配列中の配列番号 通信先のアクターと、この配列番号で紐づけています net.MaxChannelSize 32768 #UE4 | @UNREALENGINE

143.

35番 35番 8番 8番 FNetworkGUID 10番 #UE4 | @UNREALENGINE 10番

144.

FNetworkGUID 32ビット整数のID。これを使ってプロセス間のオブジェクトを紐づけます レベルに配置されているような静的なものは奇数、 動的なものは偶数が割り当てられます サーバー側で初めてプロパティとして扱う必要が出たときにObjectに対して割り 当てられます 複製対象のActorに限らずに、通信内容に含まれるすべてオブジェクトが 対象になります。(例えばプレイヤーが立っている床など) net.ListNetGUIDsでどのアクターが登録されているか確認することができます #UE4 | @UNREALENGINE

145.

Blueprintで見てみます #UE4 | @UNREALENGINE

146.

#UE4 | @UNREALENGINE

147.

#UE4 | @UNREALENGINE

148.

動かしてみると・・・ Server: PlayerCameraManager1 Client 1: Server: ThirdPersonCharacter Client 1: ThirdPersonCharacter1 Server: Linear_Stair_StaticMesh Client 1: Linear_Stair_StaticMesh Server: Wall11 Client 1: Wall11 Server: LeftArm_StaticMesh Client 1: LeftArm_StaticMesh Server: PlayerState1 Client 1: PlayerState Server: GameNetworkManager Client 1: Server: AbstractNavData-1 Client 1: Server: WorldInfo Client 1: WorldInfo #UE4 | @UNREALENGINE 送り先のワールドに 存在しないアクターは NULLになる

149.

Bunch 束 #UE4 | @UNREALENGINE

150.

パケット #UE4 | @UNREALENGINE

151.

Bunch UE4のレプリケーション処理から出力されたデータの単位 基本的に1ReplicatedActor=1Bunch 一つのパケットに複数のBunchが格納されています 各Bunchには前述のChannelIndexが格納されていて、 然るべきアクターに届けられます ( UNetConnection::ReceivedPacket 参照) ネットワークに送信されるパケットには複数のBunchが含まれます #UE4 | @UNREALENGINE

152.

受信応答 ACK/NAK #UE4 | @UNREALENGINE

153.

受信返答OK/NG - ACK / NAK ACK - ACKnowledgement NAK - Negative-AcKnowledgement ネットワーク処理の中での一般的な単語で UE4の専門用語ではありません パケットが受信されたかどうかを表します ビット列の形でパケットのヘッダに書き込まれていて、重要なパケットのやり取 りが行われたかどうかの確認や、Reliableなやり取りの再送信などに利用される ます #UE4 | @UNREALENGINE

154.

変数の複製 と 遠隔関数呼び出し #UE4 | @UNREALENGINE

155.

#UE4 | @UNREALENGINE

156.

遠隔関数呼び出し( RPC ) #UE4 | @UNREALENGINE

157.

Multicast 「うまく動かないからRPC」 は後で困りがちです #UE4 | @UNREALENGINE

158.

まず変数の複製で 出来ないか熟慮しましょう #UE4 | @UNREALENGINE

159.

こういうものはRPC向け ⚫ RPCは「イベント」です ⚫ 10秒後に無くてもいいもの ⚫ 回数が重要なもの ⚫ ⚫ 音声 VFX生成 #UE4 | @UNREALENGINE

160.

ReliableRPC 関数呼び出しの直後にいきなり、パケットのバッファに乗ります その分、他の情報が乗るスペースが減るので注意してください 非ReliableRPCは呼び出しが間引かれる可能性がありますが、 ReliableRPCは呼び出し回数分かならず処理されます 相手からのNak返答によりパケットを再送します Reliableであったとしても距離などでActorChannelが開いていない場合、 RPCは送信されません #UE4 | @UNREALENGINE

161.

RPC RPC RPC レプ #UE4 | @UNREALENGINE RPC レプ レプ レプ レプ

162.

RPC 残り RPC RPC RPC #UE4 | @UNREALENGINE レプ レプ レプ レプ レプ

163.

RPC レプ レプ RPC RPC RPC #UE4 | @UNREALENGINE レプ レプ レプ

164.

変数の複製 PropertyReplication #UE4 | @UNREALENGINE

165.

「変数の複製」は裏切らない #UE4 | @UNREALENGINE

166.

こういうものは変数の複製向け ⚫ アクターの状態を表す変数 ⚫ 途中参加したときに復元しないと困るプロパティ ⚫ 10秒後に失われては困るもの ⚫ ⚫ ⚫ ライフ 所持アイテム キャラクターの見た目 #UE4 | @UNREALENGINE

167.

変数の書き換えは慎重に //アクセサを経由して変数を操作するのをオススメします Void ASampleActor::SetReplicatedVariable( float InValue ) { check( HasAuthority() ); //不正な操作が起きないように ReplicatedValue = InValue; } //またはAutonomousProxyからは自動でServerRPCを飛ばすなど Void ASampleActor::SetReplicatedVariable( float InValue ) { if( HasAuthority() ) { ReplicatedValue = InValue; return; } check( Role == ROLE_AutonomousProxy ); //Simulate や None の場合サーバーRPCは送信できない ServerSetReplicatedVariable( InValue ); //ServerRPC } #UE4 | @UNREALENGINE

168.

Driver編まとめ ● Stat netを実行した時に表示されるよう なパラメータがドライバーの中で制御さ れている ● NetworkDriverがレベルに紐づくことに よってマルチプレイが実現されている #UE4 | @UNREALENGINE

169.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

170.

キャラクター ムーブメント #UE4 | @UNREALENGINE 一人用ならうまく移動できる のにマルチにすると 挙動がおかしい・・・ なにが起きているのか見てみ ましょう

171.

サーバー #UE4 | @UNREALENGINE クライアント

172.

ガクガクしすぎて 気分が悪くなってきました #UE4 | @UNREALENGINE

173.

クライアントで アクターの移動 移動情報を元に サーバー上で実際に 移動してみる 移動結果の座標が クライアントが送って 来た座標と全然違う! 移動情報 うそつき! 移動情報を収集して サーバーに送る うわ・・・ サーバーめっちゃ 怒ってる! 座標を戻す アクターの移動 #UE4 | @UNREALENGINE

174.

サーバー上でも 「移動」します! #UE4 | @UNREALENGINE

175.

移動情報の送信 void ServerMove( float TimeStamp, FVector_NetQuantize10 InAccel, //量子化された加速度 精度は 1mm/s^2 FVector_NetQuantize100 ClientLoc, //量子化された位置 精度は 0.1mm uint8 CompressedMoveFlags, //移動フラグ ジャンプ上昇中とか uint8 ClientRoll, //オイラー表現 ControlRotationのRoll uint32 View, //オイラー表現 ControlRotationのYawとPitch UPrimitiveComponent* ClientMovementBase,//どのプリミティブ上に立っているか FName ClientBaseBoneName, //MovementBaseのどのBoneに立っているか uint8 ClientMovementMode //クライアント上でのMovementMode ); #UE4 | @UNREALENGINE

176.

移動情報の送信 void ServerMove( クライアント上のワールド時間 float TimeStamp, FVector_NetQuantize10 InAccel, //量子化された加速度 精度は 1mm/s^2 FVector_NetQuantize100 ClientLoc, //量子化された位置 精度は 0.1mm 加速ベクトル uint8 CompressedMoveFlags, //移動フラグ ジャンプ上昇中とか uint8 ClientRoll, //オイラー表現 ControlRotationのRoll uint32 View, //オイラー表現 ControlRotationのYawとPitch UPrimitiveComponent* ClientMovementBase,//どのプリミティブ上に立っているか ボタン入力など FName ClientBaseBoneName, //MovementBaseのどのBoneに立っているか uint8 ClientMovementMode //クライアント上でのMovementMode ); カメラの向き #UE4 | @UNREALENGINE

177.

移動情報の送信 void ServerMove( float TimeStamp, 位置(不正移動チェック用) FVector_NetQuantize10 InAccel, //量子化された加速度 精度は 1mm/s^2 FVector_NetQuantize100 ClientLoc, //量子化された位置 精度は 0.1mm uint8 CompressedMoveFlags, //移動フラグ ジャンプ上昇中とか 地面(不正移動チェック用) uint8 ClientRoll, //オイラー表現 ControlRotationのRoll uint32 View, //オイラー表現 ControlRotationのYawとPitch UPrimitiveComponent* ClientMovementBase,//どのプリミティブ上に立っているか FName ClientBaseBoneName, //MovementBaseのどのBoneに立っているか uint8 ClientMovementMode //クライアント上でのMovementMode 地面の関節名(不正移動チェック用) ); 移動モード(不正移動チェック用) #UE4 | @UNREALENGINE

178.

加速度と 操作用カメラ角度から 移動を復元せざるを得ない #UE4 | @UNREALENGINE

179.

パラメータの解説 #UE4 | @UNREALENGINE

180.

MoveFlag 移動に影響を与えるプレイヤーのボタン入力をビットであらわしたもの エンジンはFLAG_JumpPressedおよびFLAG_WantsToCrouchに加えて 2ビットの計4bitを予約しています FLAG_Custom_0~3はタイトルで利用可能です 拡張は以下の関数をオーバーライドして行います FSavedMove_Character::GetCompressedFlags() エンコード処理 void UCharacterMovementComponent::UpdateFromCompressedFlags() デコードおよびにキャラクターへのフラグの適用 #UE4 | @UNREALENGINE

181.

MoveFlag 例えばShooterGameではダッシュと構え移動が実装されていますが、 MoveFlagは使わずにServerRPCによるステート変更を行っています 大きな移動を伴わない場合、RPCによる実装でも許容範囲のエラーにとどまる可 能性があります まずRPCで実装して、大きな位置エラーがでるようならMoveFlagを検討するのが 良いかもしれません MoveFlagは複雑ですがネットワーク上の特殊な移動にまつわる問題を ラグを感じさせずにスマートに解決できる可能性があります 詳しくはDocs.Unrealengineの「キャラクターの移動コンポーネント」の 最後のセクションを参照してください https://docs.unrealengine.com/ja/Gameplay/Networking/CharacterMovementComponent/index.html #UE4 | @UNREALENGINE

182.

MovementMode エンジンの組み込みで「歩いている」、「落下している」など、複数のステート があります StartNewPhysicsやGetMaxSpeed関数の内部で分岐し様々な運動を再現します SetMovementModeで切り替えることができますが、Authorityの無いプロセス 上で書き換えてもサーバーには自動反映されません さらにMovementModeの差はサーバーからズレと認識されて怒られるので 正しく処理するのをオススメします CustomMovementModeを用いて拡張が可能です #UE4 | @UNREALENGINE

183.

移動速度の書き換え 同様の理由で移動速度の書き換えも 同期エラーを生み出しがちです たとえば歩く方向によって速度を変えたい というような実装をしたい場合、 ServerRPCを毎Tick呼び出すのは 現実的ではないので、 UCharacterMovementComponent::GetMaxSpeedをオーバーライドし、 加速度とカメラから速度を計算して返すようにするのをお勧めします #UE4 | @UNREALENGINE

184.

ClientCorrection調査 p.NetShowCorrections 1 を入力すると移動速度やコリジョンの差などに よって補正が発生した場合に 図のようなデバッグ表示を行うことができます またCharacterMovementComponent.cppには これらの調整を助けるための CVarがいくつか定義されているので 見てみてください #UE4 | @UNREALENGINE

185.

ClientAuthorativePosition Iniファイルで設定します サーバーでの移動後クライアントエラーが無かった時に、 ServerMoveで送られてきた位置やMovementなどをサーバー上に適用します これによって細かい誤差の蓄積を無効化し、 補正問題を解決できる可能性があります。 #UE4 | @UNREALENGINE

186.

Networkに関係したログやini https://www.slideshare.net/EpicGamesJapan/online-multiplay-game-design #UE4 | @UNREALENGINE

187.

学習用リソース 機能ウォークスルー お品書き UE4で マルチプレイゲームを作ろう #UE4 | @UNREALENGINE 動作検証方法 ネット処理の流れと単語帳 CharacterMovement ReplicationGraph

188.

ReplicationGraph UE4.20で登場 UE4.23でもまだBETAバージョン #UE4 | @UNREALENGINE

189.

Unreal Engine Tech-blog https://www.unrealengine.com/ja/tech-blog/replication-graph-overview-and-proper-replication-methods?lang=ja #UE4 | @UNREALENGINE

190.

3つのコンセプト #UE4 | @UNREALENGINE

191.

1.毎回毎回、一から名簿を 作るのはやめよう #UE4 | @UNREALENGINE

192.

2.グリッド分割済みリスト を作る #UE4 | @UNREALENGINE

193.

3.NetworkDriverの レプリケーション処理を カスタマイズしやすいように 切り出す #UE4 | @UNREALENGINE

194.

サンプルを用意しました #UE4 | @UNREALENGINE

195.

サンプル概要 50000個の2m四方キューブを動的に生成 横100個x奥500個 200m * 1000m Developmentビルド Editorからスタンドアローン、 リッスンサーバー+5クライアント で起動 ( xeon gold 6128 @3.4GHz ) #UE4 | @UNREALENGINE

196.

まずはReplicationGraph無し #UE4 | @UNREALENGINE

197.

サーバー クライアント #UE4 | @UNREALENGINE

198.

結果 stat game ● Server ReplicateActrors Time ● 138ms ● Prioritize Actors Time ● 98ms ● Consider Actors Time ● 38ms ● Replicate Actor Time ● 70calls 0.5ms ● 5つのクライアントは60fpsで動作 #UE4 | @UNREALENGINE

199.

結果 stat net Num Actors : 50,000 Num ConsideredActors : 48,000 #UE4 | @UNREALENGINE

200.

次はReplicationGraphあり #UE4 | @UNREALENGINE

201.

サーバー クライアント #UE4 | @UNREALENGINE

202.

結果ReplicationGraphアリ ● ServerReplicateActorsTime ● 5.2ms ● Prioritize Actors Time ● statには出てこない ● Consider Actors Time ● 無し ● Replicate Actor Time : 0.5ms ● 5つのクライアントは60fpsで動作 #UE4 | @UNREALENGINE

203.

Stats : ReplicationGraph有効 (参考) #UE4 | @UNREALENGINE

204.

比較 プライオリティ付けされる前にグリッド分割によって列挙されるアクターが大幅 に減っていて、列挙の負荷が無い その影響でプライオリティ付け処理とソートの負荷が大きく減った。 RepGraphナシ RepGraphアリ 改善率 考慮されたActor数 48,000 2,740 / connection x17.5 Server ReplicateActrors Time 138ms 5.2ms x26.5 Prioritize Actors Time 98ms N/A N/A Consider Actors Time 38ms 0 ∞ Replicate Actor Time 0.5ms 0.5ms 変化なし #UE4 | @UNREALENGINE

205.

CPUが喜んでる! #UE4 | @UNREALENGINE

206.

ReplicationGraph導入 まず先にお断りしますが、c++による実装が不可欠です エンジン側の実装は基本的なものだけが定義されています カスタマイズできるのが特徴なので、タイトルに応じて 適切なリストが生成できればより効果的です はじめはShooterGameサンプルにに含まれる UShooterReplicationGraph を 持ってきて動かしてみるのがお勧めです #UE4 | @UNREALENGINE

207.

まずは自分の レプリケーショングラフを プログラムします #UE4 | @UNREALENGINE

208.

プラグインの有効化 [YOURPROJECT].uprojectに対するプラグインの追加します [YOURMODULE].build.csの PrivateDevendencyModule (or PublicDependencyModule) に、 ”ReplicationGraph” モジュールを追加します #UE4 | @UNREALENGINE

209.

クラス定義 UReplicationGraphまたは その親のUReplicationDriverを継承したクラスを定義します #UE4 | @UNREALENGINE

210.

ReplicationGraphに書くべき処理 ⚫ クラス毎にどのノードに振り分けるか事前準備 ⚫ アクターが追加された時に呼ばれる関数を独自実装 ⚫ RouteAddNetworkActorToNodes ⚫ アクターが削除された時にノードから削除する関数を独自実装 ⚫ RouteRemoveNetworkActorToNodes #UE4 | @UNREALENGINE

211.

各ReplicationGraphNode それぞれのノードには以下の実装が必要です ⚫ 毎Tickごとに事前準備用に一回呼ばれる ⚫ PrepareForReplication ⚫ コネクション毎にレプリケート対象のアクターを抽出する処理 ⚫ GatherActorListsForConnection ⚫ ReplicationGraphからルーティングされたアクターの追加と削除処理 ⚫ ⚫ NotifyAddNetworkActor NotifyRemoveNetworkActor #UE4 | @UNREALENGINE

212.

PreAllocateRepList ReplicationGraph中で使うアクターリストを 格納するための配列を事前に確保してプールに 用意し、ランタイムでのアロケーションや Resize/Memcopyなどのオーバーヘッドを避け ます void USampleReplicationGraph::InitGlobalGraphNodes() { // Preallocate some replication lists. PreAllocateRepList(3, 12); PreAllocateRepList(6, 12); PreAllocateRepList(128, 64); PreAllocateRepList(512, 16); タイトルに合わせて調整する事が望ましいです 超過した場合はDevelopmentビルドであれば 右のようなReplicationGraphの ログが出力されます #UE4 | @UNREALENGINE Very large replication list size requested. NewExpectedSize: 513

213.

組み込みノード : GridSpatialization2D アクターの現在位置にあわせて グリッドに投入します 境界付近のアクターは2つ以上のセルに 投入されます ActorのCullDistanceSquaredの値を参照して 投入範囲を設定します #UE4 | @UNREALENGINE

214.

組み込みノード : Grid_Dynmic 移動するアクターはGridSpatialization2D下のDynamicに配置します 毎TickのPrepareForReplication()で、 格納されるセルの範囲が変わっていないかチェックが入ります ※50000actorで20ms以上かかります 移動するアクターが極端に多い場合は、ここを仕様に合わせて調整したり 独自実装をおススメします。 #UE4 | @UNREALENGINE

215.

組み込みノード : Grid_Staic 移動しないアクター静的なリストを生成して返すだけなのでとても早いです。 #UE4 | @UNREALENGINE

216.

組み込みノード : Grid_Dormancy Dormancyに状態にあわせて、DynamicとStaticを行ったり来たりします。 #UE4 | @UNREALENGINE

217.

自分のReplicationGraphが実装できたら DefaultEngine.iniに、実装したクラスのパスを設定して マルチプレイゲーム開始時にインスタンスを作ってもらうようにします #UE4 | @UNREALENGINE

218.

実装完了! 思う存分動かしてください #UE4 | @UNREALENGINE

219.

あれ? 私のレプリケーショングラフ 挙動があやしくない??? #UE4 | @UNREALENGINE

220.

StandAloneモードでレプリケーション グラフを一時的に無効化 -ini:Engine:[ConsoleVariables]:Net.RepDriver.Enable=0 をCommand Line Arguments に書く レプリケートグラフが原因で通信バグが 出てるのでは? と思った時に試してください。 PIEではコンソールコマンドを入力した後 PIEを立ち上げなおせばOKです #UE4 | @UNREALENGINE

221.

参考リンク LiveStreaming https://www.youtube.com/watch?v=CDnNAAzgltw UnrealFestEurope Using Replication Graph For Optimizing Real-Time Strategy Games https://www.youtube.com/watch?v=VusAHXoHF3Y #UE4 | @UNREALENGINE

222.

ReplicationGraphまとめ ⚫ こんなプロジェクトにお勧め ⚫ ⚫ ⚫ ⚫ 大人数マルチプレイを実現したい 大量の動的なアクターを処理したい サーバーの負荷を0.1msでも速くしたい 巨大なワールドでマルチプレイを行いたい ⚫ タイトルに合わせて適切なレプリケーショングラフを作るとより効果的 #UE4 | @UNREALENGINE

223.

さいごに 今回のスライドで触れられていない 機能や情報もありますが、 別の機会に紹介出来たら!と思っています 皆様是非マルチプレイに チャレンジしてみてください! グレイマン係長 #UE4 | @UNREALENGINE

224.

QiitaへのTips投稿 はじめました #UE4 | @UNREALENGINE

225.

Unreal Fest East 2019 2019 / 10 / 6 パシフィコ横浜 #UE4 | @UNREALENGINE

226.

ご清聴 ありがとうございました! #UE4 | @UNREALENGINE