---
title: [Tokyo DevDays  26&#039;] Iris And Mover Networking
tags:  #ue5 #devdays  
author: [エピック ゲームズ ジャパン](https://www.docswell.com/user/EpicGamesJapan)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/9J29XGQ1ER.jpg?width=480
description: DevDays 26&#039; での Iris と Moverをもちいた ネットワーク対応についての講演資料です
published: August 31, 26
canonical: https://www.docswell.com/s/EpicGamesJapan/KR8M99-DayDays26-Iris-And-Mover-Networking
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/9J29XGQ1ER.jpg)

DevDays 2026
UE5.8 マルチプレイアップデート
Iris &amp; Mover
Epic Games Japan,
Senior Software Engineer, Developer Relations
Takashi Suzuki


# Page. 2

![Page Image](https://bcdn.docswell.com/page/DEY48VW4JM.jpg)

Production Ready
Experimental
Iris
Mover
レプリケーションの新基盤
キャラクター移動の新基盤プラグイン
マルチプレイ時の移動同期の機能を持つ
既定で有効か：いいえ（モジュール単位でOpt-In）
既定で有効か：いいえ


# Page. 3

![Page Image](https://bcdn.docswell.com/page/VJNYQM9678.jpg)

目次
Iris
Mover


# Page. 4

![Page Image](https://bcdn.docswell.com/page/YE9PDN2RJ3.jpg)

第I部
Iris
レプリケーションを、データ指向で新設計


# Page. 5

![Page Image](https://bcdn.docswell.com/page/GE8D3K5GED.jpg)

Iris とは
サーバーとクライアント間のデータの受け渡しを行う
新しいレプリケーション(複製)システム
本スライドでは
今までのレプリケーションシステムを
レガシーレプリケーションと呼びます
ネットドライバー
サーバー
ワールド
レプリケーション
システム
ネットドライバー
レプリケーション
システム
クライアント
ワールド


# Page. 6

![Page Image](https://bcdn.docswell.com/page/LELMVZYX7R.jpg)

Iris とは
サーバーとクライアント間のデータの受け渡しを行う
新しいレプリケーション(複製)システム
ネットドライバー
サーバー
ワールド
Iris
ネットドライバー
Iris
クライアント
ワールド


# Page. 7

![Page Image](https://bcdn.docswell.com/page/4JMYGVN3JW.jpg)

レガシーシステムの限界
スケーリング
ReplicationGraph
並列化が困難
接続先毎に一から処理する
部分が多く、接続数に応じ
て負荷が単純増加
大量の接続を捌く
ReplicationGraphが外付け
学習、運用コストが高い
チャンネル/接続にまたがる
ステートが多く
複製対象への
仮想関数呼び出しが散在


# Page. 8

![Page Image](https://bcdn.docswell.com/page/PJR9Z2DR79.jpg)

Irisの柱
パフォーマンス
システムの分離
互換性
量子化(≒シリアライズ)を一
回だけ行い、
レプリケーションシステム
からワールドやアクターを
直接参照しない
開発者への負担を最小限に
接続毎にバッチ処理
アクター数と接続数で
うまくスケーリング
※シーングラフなどを見据
えた設計
タイトル側の対応は
ほとんど不要


# Page. 9

![Page Image](https://bcdn.docswell.com/page/PEXQ9D1YJX.jpg)

レガシーレプリケーションの動作
ワールド
アクター
変更検出
アクターチャンネル
優先度ソート
関連性
シリアライズ
アクター x 接続先数分 ループ


# Page. 10

![Page Image](https://bcdn.docswell.com/page/3EK9PX24ED.jpg)

Iris の 動作
ワールド
アクター
接続先1のデータストリーム
優先度付け
フィルタ
ChangeMask
デルタ圧縮
接続先2のデータストリーム
情報取得
優先度付け
フィルタ
ChangeMask
デルタ圧縮
量子化
POD
(量子化済みデータ)
接続先3のデータストリーム
優先度付け
フィルタ
ChangeMask
デルタ圧縮


# Page. 11

![Page Image](https://bcdn.docswell.com/page/L73WX54D75.jpg)

POD ( Plain Old Data )
Plain Old Data の Old は時間軸を示す形容詞ではなく
Plain Old ~ で「ただの/なんでもない」という意味
つまりmemcpyで直接扱えるタイプのただのデータ列を表します


# Page. 12

![Page Image](https://bcdn.docswell.com/page/87DK2DQ2JG.jpg)

Iris の 動作
ワールド
アクター
接続先1のデータストリーム
優先度付け
フィルタ
ChangeMask
デルタ圧縮
接続先2のデータストリーム
情報取得
優先度付け
フィルタ
ChangeMask
デルタ圧縮
量子化
POD
(量子化済みデータ)
接続先3のデータストリーム
優先度付け
フィルタ
ChangeMask
デルタ圧縮


# Page. 13

![Page Image](https://bcdn.docswell.com/page/VJPK1XLLE8.jpg)

ChangeMask の 動作
アクター
(オブジェクト)
接続先1のデータストリーム
PollingまたはPush
シャドウステート
接続先2のデータストリーム
POD
(量子化済みデータ)
接続先3のデータストリーム
ChangeMask


# Page. 14

![Page Image](https://bcdn.docswell.com/page/2EVVYLQ6EQ.jpg)

ChangeMask の 動作
コピー
アクター
(オブジェクト)
接続先1のデータストリーム
PollingまたはPush
POD
(量子化済みデータ)
ChangeMask追加
シャドウステート
接続先2のデータストリーム
接続先3のデータストリーム
ChangeMask


# Page. 15

![Page Image](https://bcdn.docswell.com/page/57GL9XW2EL.jpg)

ChangeMask の 動作
アクター
(オブジェクト)
接続先1のデータストリーム
PollingまたはPush
シャドウステート
接続先2のデータストリーム
量子化
POD
(量子化済みデータ)
接続先3のデータストリーム
ChangeMask


# Page. 16

![Page Image](https://bcdn.docswell.com/page/4EQYW839JP.jpg)

ChangeMask の 動作
アクター
(オブジェクト)
接続先1のデータストリーム
PollingまたはPush
シャドウステート
接続先2のデータストリーム
POD
(量子化済みデータ)
接続先3のデータストリーム
ChangeMask


# Page. 17

![Page Image](https://bcdn.docswell.com/page/KJ4WK2NR71.jpg)

ChangeMask の 動作
アクター
(オブジェクト)
接続先1のデータストリーム
シ
リ
ア
ラ
イ
PollingまたはPush
ズ
シャドウステート
接続先2のデータストリーム
シ
リ
ア
ラ
イ
POD
(量子化済みデータ)
ズ
参照
接続先3のデータストリーム
ChangeMask


# Page. 18

![Page Image](https://bcdn.docswell.com/page/LE1YXM5V7G.jpg)

NetSerializer
型や構造体をIrisで制御するためのシリアライザー
●
●
●
Quantize(構造体⇔POD)
Serialize(POD⇔パケット)
SerializeDelta(デルタ圧縮)
非本の型、UCLASS、USTRUCTなどのほとんどのクラスは
デフォルト実装を利用可能。 できる限りエンジンに任せることを推奨。
ただしレガシーシステムでNetSerializeが実装されていたクラスに
対してはNetSerializerを実装する必要がある


# Page. 19

![Page Image](https://bcdn.docswell.com/page/GEWGN353J2.jpg)

struct FExampleNetSerializer
{
/** 必須 Version番号 */
static constexpr uint32 Version = 0;
// 以下の各トレイトは任意。下記の既定値と異なる場合にのみ指定すればよい。
/* 少なくとも 1 つの他のシリアライザへ呼び出しを転送する意図があり、
実装可能なすべての関数を確実に実装したい場合に指定する。
*/
static constexpr bool bIsForwardingSerializer = false;
/* 接続固有のシリアライズが必要な場合に指定する。使用は避けること！
*/
static constexpr bool bHasConnectionSpeciﬁcSerialization = false;
/* CollectNetReferences の実装が必要な場合に指定する。*/
static constexpr bool bHasCustomNetReference = false;
/* シリアライザが動的ステートを必要とする場合に指定する。
* CloneDynamicState と FreeDynamicState の実装が必須になる。*/
static constexpr bool bHasDynamicState = false;
/** 同値デルタ圧縮方式が望ましくない場合にfalse を設定する。
* 例えば、シリアライザがそのステートに対して1 ビットしか書き込まない場合など。*/
static constexpr bool bUseDefaultDelta = true;
/** 必須 外部ステートのサイズとアライメントを算出し、一部の関数の既定実装を
提供する */
typedef FSomeSourceType SourceType;
/** QuantizedType の typedef は任意。ただしSourceType が POD でない場合は必須。
* 指定しない場合はSourceType とみなされる。QuantizedType は POD である必要がある。 */
typedef FSomePodType QuantizedType;
/** 必須 ConﬁgType の typedef は必須。 */
typedef FNetSerializerConﬁg ConﬁgType;
/** ほぼ必須 DefaultConﬁg は任意だが強く推奨される。*/
inline static const ConﬁgType DefaultConﬁg;
/** 必須。Serialize は、シリアライゼーションコンテキストから提供される
* ビットストリームへ量子化済みデータを書き込む責務を持つ。*/
static void Serialize(FNetSerializationContext&amp;, const FNetSerializeArgs&amp;);
/** 必須。Deserialize は、シリアライゼーションコンテキストから提供される
* ビットストリームから量子化済みデータを読み取る責務を持つ。*/
static void Deserialize(FNetSerializationContext&amp;, const FNetDeserializeArgs&amp;);
/** 任意。Serialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。*/
static void SerializeDelta(FNetSerializationContext&amp;, const FNetSerializeDeltaArgs&amp;);
/** 任意。Deserialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。 */
static void DeserializeDelta(FNetSerializationContext&amp;, const FNetDeserializeDeltaArgs&amp;);
/** 任意。 ソースデータを、高速にシリアライズできるPOD 形式へ変換する。
* 量子化はオブジェクトごと・フレームごとに高々1 回しか実行されないため、
* シリアライズを高速化する目的でやや重い計算を行うのに絶好の機会である。
*/
static void Quantize(FNetSerializationContext&amp;, const FNetQuantizeArgs&amp;);
/** 任意。ただし QuantizedType の typedef または Quantize の実装がある場合は必須。
* dequantize 関数は、量子化されたステートを妥当なソースデータ形式へ変換する責務を持つ。
* 変換結果は、量子化前の元のソースデータとおおむね等しくなる。
*/
static void Dequantize(FNetSerializationContext&amp;, const FNetDequantizeArgs&amp;);
/** 任意。あるデータが他のデータと等しいかどうかを判定する。
* 既定の実装は等価演算子を使用する。*/
static bool IsEqual(FNetSerializationContext&amp;, const FNetIsEqualArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* 量子化済みデータを、あるステートバッファから別のステートバッファへクローンする。
*/
static void CloneDynamicState(FNetSerializationContext&amp;, const FNetCloneDynamicStateArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* ステートバッファ内の動的確保を解放し、データを既定ステートへリセットする。
*/
static void FreeDynamicState(FNetSerializationContext&amp;, const FNetFreeDynamicStateArgs&amp;);
};
//シリアライザとして実体化
UE_NET_IMPLEMENT_SERIALIZER(FExampleNetSerializer);
//Irisに登録
UE_NET_IMPLEMENT_FORWARDING_NETSERIALIZER_AND_REGISTRY_DELEGATES(ExampleNetSeri
alizer, FExampleNetSerializer)


# Page. 20

![Page Image](https://bcdn.docswell.com/page/47ZL3VNGJ3.jpg)

struct FExampleNetSerializer
{
/** 必須 Version番号 */
static constexpr uint32 Version = 0;
// 以下の各トレイトは任意。下記の既定値と異なる場合にのみ指定すればよい。
/* 少なくとも 1 つの他のシリアライザへ呼び出しを転送する意図があり、
実装可能なすべての関数を確実に実装したい場合に指定する。
*/
static constexpr bool bIsForwardingSerializer = false;
/* 接続固有のシリアライズが必要な場合に指定する。使用は避けること！
*/
static constexpr bool bHasConnectionSpeciﬁcSerialization = false;
/* CollectNetReferences の実装が必要な場合に指定する。*/
static constexpr bool bHasCustomNetReference = false;
/* シリアライザが動的ステートを必要とする場合に指定する。
* CloneDynamicState と FreeDynamicState の実装が必須になる。*/
static constexpr bool bHasDynamicState = false;
/** 同値デルタ圧縮方式が望ましくない場合にfalse を設定する。
* 例えば、シリアライザがそのステートに対して1 ビットしか書き込まない場合など。*/
static constexpr bool bUseDefaultDelta = true;
/** 必須 外部ステートのサイズとアライメントを算出し、一部の関数の既定実装を
提供する */
typedef FSomeSourceType SourceType;
/** QuantizedType の typedef は任意。ただしSourceType が POD でない場合は必須。
* 指定しない場合はSourceType とみなされる。QuantizedType は POD である必要がある。 */
typedef FSomePodType QuantizedType;
/** 必須 ConﬁgType の typedef は必須。 */
typedef FNetSerializerConﬁg ConﬁgType;
/** ほぼ必須 DefaultConﬁg は任意だが強く推奨される。*/
inline static const ConﬁgType DefaultConﬁg;
/** 必須。Serialize は、シリアライゼーションコンテキストから提供される
* ビットストリームへ量子化済みデータを書き込む責務を持つ。*/
static void Serialize(FNetSerializationContext&amp;, const FNetSerializeArgs&amp;);
/** 必須。Deserialize は、シリアライゼーションコンテキストから提供される
* ビットストリームから量子化済みデータを読み取る責務を持つ。*/
static void Deserialize(FNetSerializationContext&amp;, const FNetDeserializeArgs&amp;);
/** 任意。Serialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。*/
static void SerializeDelta(FNetSerializationContext&amp;, const FNetSerializeDeltaArgs&amp;);
/** 任意。Deserialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。 */
static void DeserializeDelta(FNetSerializationContext&amp;, const FNetDeserializeDeltaArgs&amp;);
/** 任意。 ソースデータを、高速にシリアライズできるPOD 形式へ変換する。
* 量子化はオブジェクトごと・フレームごとに高々1 回しか実行されないため、
* シリアライズを高速化する目的でやや重い計算を行うのに絶好の機会である。
*/
static void Quantize(FNetSerializationContext&amp;, const FNetQuantizeArgs&amp;);
/** 任意。ただし QuantizedType の typedef または Quantize の実装がある場合は必須。
* dequantize 関数は、量子化されたステートを妥当なソースデータ形式へ変換する責務を持つ。
* 変換結果は、量子化前の元のソースデータとおおむね等しくなる。
*/
static void Dequantize(FNetSerializationContext&amp;, const FNetDequantizeArgs&amp;);
/** 任意。あるデータが他のデータと等しいかどうかを判定する。
* 既定の実装は等価演算子を使用する。*/
static bool IsEqual(FNetSerializationContext&amp;, const FNetIsEqualArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* 量子化済みデータを、あるステートバッファから別のステートバッファへクローンする。
*/
static void CloneDynamicState(FNetSerializationContext&amp;, const FNetCloneDynamicStateArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* ステートバッファ内の動的確保を解放し、データを既定ステートへリセットする。
*/
static void FreeDynamicState(FNetSerializationContext&amp;, const FNetFreeDynamicStateArgs&amp;);
};
//シリアライザとして実体化
UE_NET_IMPLEMENT_SERIALIZER(FExampleNetSerializer);
//Irisに登録
UE_NET_IMPLEMENT_FORWARDING_NETSERIALIZER_AND_REGISTRY_DELEGATES(ExampleNetSeri
alizer, FExampleNetSerializer)


# Page. 21

![Page Image](https://bcdn.docswell.com/page/YJ6WX58QJV.jpg)

struct FExampleNetSerializer
{
/** 必須 Version番号 */
static constexpr uint32 Version = 0;
// 以下の各トレイトは任意。下記の既定値と異なる場合にのみ指定すればよい。
/* 少なくとも 1 つの他のシリアライザへ呼び出しを転送する意図があり、
実装可能なすべての関数を確実に実装したい場合に指定する。
*/
static constexpr bool bIsForwardingSerializer = false;
/* 接続固有のシリアライズが必要な場合に指定する。使用は避けること！
*/
static constexpr bool bHasConnectionSpeciﬁcSerialization = false;
/* CollectNetReferences の実装が必要な場合に指定する。*/
static constexpr bool bHasCustomNetReference = false;
/* シリアライザが動的ステートを必要とする場合に指定する。
* CloneDynamicState と FreeDynamicState の実装が必須になる。*/
static constexpr bool bHasDynamicState = false;
/** 同値デルタ圧縮方式が望ましくない場合にfalse を設定する。
* 例えば、シリアライザがそのステートに対して1 ビットしか書き込まない場合など。*/
static constexpr bool bUseDefaultDelta = true;
/** 必須 外部ステートのサイズとアライメントを算出し、一部の関数の既定実装を
提供する */
typedef FSomeSourceType SourceType;
/** QuantizedType の typedef は任意。ただしSourceType が POD でない場合は必須。
* 指定しない場合はSourceType とみなされる。QuantizedType は POD である必要がある。 */
typedef FSomePodType QuantizedType;
/** 必須 ConﬁgType の typedef は必須。 */
typedef FNetSerializerConﬁg ConﬁgType;
/** ほぼ必須 DefaultConﬁg は任意だが強く推奨される。*/
inline static const ConﬁgType DefaultConﬁg;
/** 必須。Serialize は、シリアライゼーションコンテキストから提供される
* ビットストリームへ量子化済みデータを書き込む責務を持つ。*/
static void Serialize(FNetSerializationContext&amp;, const FNetSerializeArgs&amp;);
/** 必須。Deserialize は、シリアライゼーションコンテキストから提供される
* ビットストリームから量子化済みデータを読み取る責務を持つ。*/
static void Deserialize(FNetSerializationContext&amp;, const FNetDeserializeArgs&amp;);
/** 任意。Serialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。*/
static void SerializeDelta(FNetSerializationContext&amp;, const FNetSerializeDeltaArgs&amp;);
/** 任意。Deserialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。 */
static void DeserializeDelta(FNetSerializationContext&amp;, const FNetDeserializeDeltaArgs&amp;);
/** 任意。 ソースデータを、高速にシリアライズできるPOD 形式へ変換する。
* 量子化はオブジェクトごと・フレームごとに高々1 回しか実行されないため、
* シリアライズを高速化する目的でやや重い計算を行うのに絶好の機会である。
*/
static void Quantize(FNetSerializationContext&amp;, const FNetQuantizeArgs&amp;);
/** 任意。ただし QuantizedType の typedef または Quantize の実装がある場合は必須。
* dequantize 関数は、量子化されたステートを妥当なソースデータ形式へ変換する責務を持つ。
* 変換結果は、量子化前の元のソースデータとおおむね等しくなる。
*/
static void Dequantize(FNetSerializationContext&amp;, const FNetDequantizeArgs&amp;);
/** 任意。あるデータが他のデータと等しいかどうかを判定する。
* 既定の実装は等価演算子を使用する。*/
static bool IsEqual(FNetSerializationContext&amp;, const FNetIsEqualArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* 量子化済みデータを、あるステートバッファから別のステートバッファへクローンする。
*/
static void CloneDynamicState(FNetSerializationContext&amp;, const FNetCloneDynamicStateArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* ステートバッファ内の動的確保を解放し、データを既定ステートへリセットする。
*/
static void FreeDynamicState(FNetSerializationContext&amp;, const FNetFreeDynamicStateArgs&amp;);
};
//シリアライザとして実体化
UE_NET_IMPLEMENT_SERIALIZER(FExampleNetSerializer);
//Irisに登録
UE_NET_IMPLEMENT_FORWARDING_NETSERIALIZER_AND_REGISTRY_DELEGATES(ExampleNetSeri
alizer, FExampleNetSerializer)


# Page. 22

![Page Image](https://bcdn.docswell.com/page/GJ5MXY92J4.jpg)

struct FExampleNetSerializer
{
/** 必須 Version番号 */
static constexpr uint32 Version = 0;
// 以下の各トレイトは任意。下記の既定値と異なる場合にのみ指定すればよい。
/* 少なくとも 1 つの他のシリアライザへ呼び出しを転送する意図があり、
実装可能なすべての関数を確実に実装したい場合に指定する。
*/
static constexpr bool bIsForwardingSerializer = false;
/* 接続固有のシリアライズが必要な場合に指定する。使用は避けること！
*/
static constexpr bool bHasConnectionSpeciﬁcSerialization = false;
/* CollectNetReferences の実装が必要な場合に指定する。*/
static constexpr bool bHasCustomNetReference = false;
/* シリアライザが動的ステートを必要とする場合に指定する。
* CloneDynamicState と FreeDynamicState の実装が必須になる。*/
static constexpr bool bHasDynamicState = false;
/** 同値デルタ圧縮方式が望ましくない場合にfalse を設定する。
* 例えば、シリアライザがそのステートに対して1 ビットしか書き込まない場合など。*/
static constexpr bool bUseDefaultDelta = true;
/** 必須 外部ステートのサイズとアライメントを算出し、一部の関数の既定実装を
提供する */
typedef FSomeSourceType SourceType;
/** QuantizedType の typedef は任意。ただしSourceType が POD でない場合は必須。
* 指定しない場合はSourceType とみなされる。QuantizedType は POD である必要がある。 */
typedef FSomePodType QuantizedType;
/** 必須 ConﬁgType の typedef は必須。 */
typedef FNetSerializerConﬁg ConﬁgType;
/** ほぼ必須 DefaultConﬁg は任意だが強く推奨される。*/
inline static const ConﬁgType DefaultConﬁg;
/** 必須。Serialize は、シリアライゼーションコンテキストから提供される
* ビットストリームへ量子化済みデータを書き込む責務を持つ。*/
static void Serialize(FNetSerializationContext&amp;, const FNetSerializeArgs&amp;);
/** 必須。Deserialize は、シリアライゼーションコンテキストから提供される
* ビットストリームから量子化済みデータを読み取る責務を持つ。*/
static void Deserialize(FNetSerializationContext&amp;, const FNetDeserializeArgs&amp;);
/** 任意。Serialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。*/
static void SerializeDelta(FNetSerializationContext&amp;, const FNetSerializeDeltaArgs&amp;);
/** 任意。Deserialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。 */
static void DeserializeDelta(FNetSerializationContext&amp;, const FNetDeserializeDeltaArgs&amp;);
/** 任意。 ソースデータを、高速にシリアライズできるPOD 形式へ変換する。
* 量子化はオブジェクトごと・フレームごとに高々1 回しか実行されないため、
* シリアライズを高速化する目的でやや重い計算を行うのに絶好の機会である。
*/
static void Quantize(FNetSerializationContext&amp;, const FNetQuantizeArgs&amp;);
/** 任意。ただし QuantizedType の typedef または Quantize の実装がある場合は必須。
* dequantize 関数は、量子化されたステートを妥当なソースデータ形式へ変換する責務を持つ。
* 変換結果は、量子化前の元のソースデータとおおむね等しくなる。
*/
static void Dequantize(FNetSerializationContext&amp;, const FNetDequantizeArgs&amp;);
/** 任意。あるデータが他のデータと等しいかどうかを判定する。
* 既定の実装は等価演算子を使用する。*/
static bool IsEqual(FNetSerializationContext&amp;, const FNetIsEqualArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* 量子化済みデータを、あるステートバッファから別のステートバッファへクローンする。
*/
static void CloneDynamicState(FNetSerializationContext&amp;, const FNetCloneDynamicStateArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* ステートバッファ内の動的確保を解放し、データを既定ステートへリセットする。
*/
static void FreeDynamicState(FNetSerializationContext&amp;, const FNetFreeDynamicStateArgs&amp;);
};
//シリアライザとして実体化
UE_NET_IMPLEMENT_SERIALIZER(FExampleNetSerializer);
//Irisに登録
UE_NET_IMPLEMENT_FORWARDING_NETSERIALIZER_AND_REGISTRY_DELEGATES(ExampleNetSeri
alizer, FExampleNetSerializer)


# Page. 23

![Page Image](https://bcdn.docswell.com/page/LE3WX5Y1E5.jpg)

struct FExampleNetSerializer
{
/** 必須 Version番号 */
static constexpr uint32 Version = 0;
// 以下の各トレイトは任意。下記の既定値と異なる場合にのみ指定すればよい。
/* 少なくとも 1 つの他のシリアライザへ呼び出しを転送する意図があり、
実装可能なすべての関数を確実に実装したい場合に指定する。
*/
static constexpr bool bIsForwardingSerializer = false;
/* 接続固有のシリアライズが必要な場合に指定する。使用は避けること！
*/
static constexpr bool bHasConnectionSpeciﬁcSerialization = false;
/* CollectNetReferences の実装が必要な場合に指定する。*/
static constexpr bool bHasCustomNetReference = false;
/* シリアライザが動的ステートを必要とする場合に指定する。
* CloneDynamicState と FreeDynamicState の実装が必須になる。*/
static constexpr bool bHasDynamicState = false;
/** 同値デルタ圧縮方式が望ましくない場合にfalse を設定する。
* 例えば、シリアライザがそのステートに対して1 ビットしか書き込まない場合など。*/
static constexpr bool bUseDefaultDelta = true;
/** 必須 外部ステートのサイズとアライメントを算出し、一部の関数の既定実装を
提供する */
typedef FSomeSourceType SourceType;
/** QuantizedType の typedef は任意。ただしSourceType が POD でない場合は必須。
* 指定しない場合はSourceType とみなされる。QuantizedType は POD である必要がある。 */
typedef FSomePodType QuantizedType;
/** 必須 ConﬁgType の typedef は必須。 */
typedef FNetSerializerConﬁg ConﬁgType;
/** ほぼ必須 DefaultConﬁg は任意だが強く推奨される。*/
inline static const ConﬁgType DefaultConﬁg;
/** 必須。Serialize は、シリアライゼーションコンテキストから提供される
* ビットストリームへ量子化済みデータを書き込む責務を持つ。*/
static void Serialize(FNetSerializationContext&amp;, const FNetSerializeArgs&amp;);
/** 必須。Deserialize は、シリアライゼーションコンテキストから提供される
* ビットストリームから量子化済みデータを読み取る責務を持つ。*/
static void Deserialize(FNetSerializationContext&amp;, const FNetDeserializeArgs&amp;);
/** 任意。Serialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。*/
static void SerializeDelta(FNetSerializationContext&amp;, const FNetSerializeDeltaArgs&amp;);
/** 任意。Deserialize と同じだが、ビットパッキングのためにACK 済みの前ステートが
* 提供される。既定では同値最適化を行う実装が提供される（
1 ビットのコストがかかる）。 */
static void DeserializeDelta(FNetSerializationContext&amp;, const FNetDeserializeDeltaArgs&amp;);
/** 任意。 ソースデータを、高速にシリアライズできるPOD 形式へ変換する。
* 量子化はオブジェクトごと・フレームごとに高々1 回しか実行されないため、
* シリアライズを高速化する目的でやや重い計算を行うのに絶好の機会である。
*/
static void Quantize(FNetSerializationContext&amp;, const FNetQuantizeArgs&amp;);
/** 任意。ただし QuantizedType の typedef または Quantize の実装がある場合は必須。
* dequantize 関数は、量子化されたステートを妥当なソースデータ形式へ変換する責務を持つ。
* 変換結果は、量子化前の元のソースデータとおおむね等しくなる。
*/
static void Dequantize(FNetSerializationContext&amp;, const FNetDequantizeArgs&amp;);
/** 任意。あるデータが他のデータと等しいかどうかを判定する。
* 既定の実装は等価演算子を使用する。*/
static bool IsEqual(FNetSerializationContext&amp;, const FNetIsEqualArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* 量子化済みデータを、あるステートバッファから別のステートバッファへクローンする。
*/
static void CloneDynamicState(FNetSerializationContext&amp;, const FNetCloneDynamicStateArgs&amp;);
/** bHasDynamicState が true の場合は必須。
* ステートバッファ内の動的確保を解放し、データを既定ステートへリセットする。
*/
static void FreeDynamicState(FNetSerializationContext&amp;, const FNetFreeDynamicStateArgs&amp;);
};
//シリアライザとして実体化
UE_NET_IMPLEMENT_SERIALIZER(FExampleNetSerializer);
//Irisに登録
UE_NET_IMPLEMENT_FORWARDING_NETSERIALIZER_AND_REGISTRY_DELEGATES(ExampleNetSeri
alizer, FExampleNetSerializer)


# Page. 24

![Page Image](https://bcdn.docswell.com/page/8EDK2D5K7G.jpg)

量子化
元データをPODに変換する処理
クラスごとの特殊な実装を加えることが可能で
例えば浮動小数点値を整数型に変換する実装などがある (FVector_NetQuantizeなど)


# Page. 25

![Page Image](https://bcdn.docswell.com/page/V7PK1XG3J8.jpg)

デルタ圧縮
シリアライズのタイミングでビットレベルのデルタ圧縮がかかる
●
二つのデルタ圧縮
○ Same-value デルタ圧縮
■ 値が変化していない場合に1bitに圧縮
○ ベースライン デルタ圧縮
■ NetSerializerにSerializeDelta/DeserializeDeltaがが実装されている型が対象
■ 定期的に更新されるベースラインからのビットレベル差分でデータが送信される
● net.Iris.MinimumNumberOfFramesBetweenBaselines(デフォルト値60)
[/Script/IrisCore.ObjectReplicationBridgeConﬁg]
; Pawn派生クラスはエンジンの定義で有効化されている
; 指定したクラスの派生クラスにも適用される
+DeltaCompressionConﬁgs=(ClassName=/Script/MyGame.MyActor)
; 継承で有効になったクラスを個別に無効化したい場合
+DeltaCompressionConﬁgs=(ClassName=/Script/MyGame.MyLightweightPawn, bEnableDeltaCompression=false)


# Page. 26

![Page Image](https://bcdn.docswell.com/page/2JVVYL6NJQ.jpg)

量子化やデルタ圧縮が実装されている型
量子化
デルタ
FVector
✕
✕
完全精度 (変更時196bit送信)
FVector_NetQuantize
〇
〇
整数キャスト
FVector_NetQuantize10
〇
〇
3bit固定小数点
FVector_NetQuantize100
〇
〇
7bit固定小数点
FRotator
〇
〇
各要素16bitに
FQuat
〇
✕
wを省略&amp;復元
int32/int64/uint32/uint64
✕
〇
float/double
✕
〇
FTransform
✕
✕
構造体 : FQuat + FVector + FVector に分解
FMatrix
✕
✕
構造体 : ( FPlane + Double ) x 4 に分解 (1012bits)
型


# Page. 27

![Page Image](https://bcdn.docswell.com/page/5EGL9XN5JL.jpg)

FastArraySerializer
FastArraySerializerを使ったクラスはIrisFastArraySerializerに基底クラスを置換する
コードサンプルはLyra等のソース内を
●
●
●
FastArrayは要素のPush(MarkItemDirty)に対応しているので
全要素に対する比較を行わなくて良くなる
最終的に生成されるシリアライズ済みデータは同等
インデックス付変更コールバックを利用可能
○ PreReplicatedRemove
○ PostReplicatedAdd/Change/Receive
○ RepNotifyは配列全体の変更しか検出できない


# Page. 28

![Page Image](https://bcdn.docswell.com/page/4JQYW8QL7P.jpg)

配列ののChangeMask
TArray型配列やFastArraySerializerの配列は
63bitのChangeMaskを持ち部分更新を行う
配列長64要素を超えるときモジュロ演算
(Index % 63)で対応ビットを選択しマスクを共有する
Index 0に書き込み
注意！
検証のためデルタ圧縮未適用
●
配列長64の配列に対する部分書き込みの例
○ Index 0 または 63 に書き込み
■ 0 と 63 の二つが送信
○ Index 1~62 に書き込み
■ 1つだけ送信
デルタ圧縮でまき込まれる要素を圧縮できると良い
Index 1に書き込み


# Page. 29

![Page Image](https://bcdn.docswell.com/page/K74WK2N5E1.jpg)

FastArrayとDelta圧縮のパフォーマンステスト
256x256x4byte(256KB)の
テクスチャをレプリケートするテスト
タイルで分割 (16pixelx16pixel)
256タイルの配列で制御
●
●
●
TArray+デルタ圧縮なし
IrisFastArray+デルタ圧縮なし
IrisFastArray+デルタ圧縮あり


# Page. 30

![Page Image](https://bcdn.docswell.com/page/LJ1YXM52EG.jpg)

FastArrayとDelta圧縮のパフォーマンス
TArray配列でPushなしだと
配列全体をなめるプーリングが毎Tick処理されてしまう


# Page. 31

![Page Image](https://bcdn.docswell.com/page/GJWGN35272.jpg)

FastArrayとDelta圧縮のパフォーマンス
TArray
FastArray デルタ圧縮なし
FastArray デルタ圧縮あり
1タイル書き込みで4タイル巻き込まれる例
デルタ圧縮で巻き込まれタイルが
8740bit から 516bitに圧縮されている


# Page. 32

![Page Image](https://bcdn.docswell.com/page/4EZL3VN473.jpg)

Filter
アクターの情報をクライアントに送るべきどうかの関連性(Relevancy)を制御する仕組み
Static
Exculusion
Dynamic
Owner
NetObjectFilter
Inclusion


# Page. 33

![Page Image](https://bcdn.docswell.com/page/Y76WX58G7V.jpg)

Filter : NetObjectFilter
空間フィルタなどの動的なフィルタ
クラスごとに一つのNetObjectFilterに属することができる
組み込みのNetObjectGridWorldLocFilterは
ReplicationGraphの2DGrid相当の機能を持つ
適切な設定がおこなわれているかは以下のコンソールコマンドで確認する
Net.Iris.PrintDynamicFilterClassConﬁg
Net.Iris.PrintDynamicFilterClassConﬁgIssues
[/Script/IrisCore.NetObjectFilterDeﬁnitions]
+NetObjectFilterDeﬁnitions=(FilterName=Spatial, ClassName=/Script/IrisCore.NetObjectGridWorldLocFilter, ConﬁgClassName=/Script/IrisCore.NetObjectGridFilterConﬁg)
+NetObjectFilterDeﬁnitions=(FilterName=NotRouted, ClassName=/Script/IrisCore.FilterOutNetObjectFilter, ConﬁgClassName=/Script/IrisCore.FilterOutNetObjectFilterConﬁg)
DefaultSpatialFilterName=Spatial
;+FilterConﬁgs=(ClassName=/Script/Engine.LevelScriptActor, DynamicFilterName=NotRouted) ; NotRouted means that this type will not be replicated
[/Script/IrisCore.NetObjectGridFilterConﬁg]
CellSizeX=10000.0
CellSizeY=10000.0


# Page. 34

![Page Image](https://bcdn.docswell.com/page/G75MXY9X74.jpg)

Filter : Exclusion と Inclusion
Exclusion:特定のグループに属したアクターを接続先ごとに通信から除外する
Inclusion:特定のグループに属しているObjectフィルタで除外されたアクターに対して
接続単位で除外を取り消すことができる
●
●
●
グループはInclusionFilterGroupかExclusionFilterGroupのどちらかに設定されている
アクターを１つまたは複数のグループに属させる
各グループに対して接続先ごとに許可を不許可を設定できる


# Page. 35

![Page Image](https://bcdn.docswell.com/page/9J29XG2QER.jpg)

Filter : Exclusion と Inclusion
NetObjectFilter
To ConnectionA
To ConnectionB
To ConnectionC
Group Spectator :
Exculution
Group Wolves :
Inclusion
Disallow
Disallow
Disallow
Arrow
Allow
Disallow


# Page. 36

![Page Image](https://bcdn.docswell.com/page/DEY48VYYJM.jpg)

Prioritizer
クラスごとにプライオリタイザを割り当ててアクター毎の送信優先度を制御
●
●
●
●
●
●
優先度でソートして送信
○ 先送りになった複製対象は優先度を蓄積 (そのうち送信される)
蓄積した値が1未満は送信対象から除外。送信間隔制御として機能する
○ 設定値0.2なら、5tickに1回の送信チャンス
レガシーではアクター毎のNetPriorityをベースに距離などの係数を乗算していたがIrisは即値
ini内で NetObjectPrioritizerDeﬁnitionsの配列のうち
有効な一番最初の定義がデフォルト設定になる
AlwaysRelevantやOnlyRelevantToOwnerが設定されたアクターは
静的プライオリティとして制御されてアクターのNetPriorityを参照する
手動で静的プライオリティをあたえる
UE::Net::FReplicationSystemUtil::SetStaticPriority(ThisActor, 1.0f);


# Page. 37

![Page Image](https://bcdn.docswell.com/page/VJNYQMPR78.jpg)

Prioritizer
デフォルトで距離ベースのPrioritizerが設定されています
NetObjectPrioritizerDeﬁnitionsの
一つ目がデフォルト
[/Script/IrisCore.NetObjectPrioritizerDeﬁnitions]
+NetObjectPrioritizerDeﬁnitions=(PrioritizerName=DefaultPrioritizer, ClassName=/Script/IrisCore.SphereNetObjectPrioritizer, ConﬁgClassName=/Script/IrisCore.SphereNetObjectPrioritizerConﬁg)
+NetObjectPrioritizerDeﬁnitions=(PrioritizerName=PlayerStatePrioritizer, ClassName=/Script/IrisCore.NetObjectCountLimiter, ConﬁgClassName=/Script/Engine.PlayerStateCountLimiterConﬁg)
; PrioritizerConﬁgs
; PlayerStateは位置情報を持たないのでPlayerStatePrioritizerを割り当てる NetPriorityは無視されることに注意
+PrioritizerConﬁgs=(ClassName=/Script/Engine.PlayerState, PrioritizerName=PlayerStatePrioritizer, bForceEnableOnAllInstances=true)
[/Script/IrisCore.SphereNetObjectPrioritizerConﬁg]
; エンジン既定: InnerRadius=2000, OuterRadius=10000
InnerRadius=5000.0
OuterRadius=30000.0
InnerPriority=1.0
OuterPriority=0.2
OutsidePriority=0.1
プライオリタイザーの
パラメータオーバーライド
bForceEnableOnAllInstanceは
AlwaysRelevantでもPrioritizerを有効化するフラグ


# Page. 38

![Page Image](https://bcdn.docswell.com/page/YE9PDN3ZJ3.jpg)

ポーリングとPushModel
プッシュモデルはポーリング処理負荷を軽減する
特にプロパティ書き換えタイミングが
限定されたアクターに対して有効
void AActor::GetLifetimeReplicatedProps( TArray&lt; FLifetimeProperty &gt; &amp; OutLifetimeProps ) const
{
FDoRepLifetimeParams SharedParams;
SharedParams.bIsPushBased = true;
DOREPLIFETIME_WITH_PARAMS_FAST(AActor, bReplicateMovement, SharedParams);
…
}
void AActor::SetReplicatingMovement(bool bInReplicateMovement)
{
bReplicateMovement = bInReplicateMovement;
MARK_PROPERTY_DIRTY_FROM_NAME(AActor, bReplicateMovement, this);
}
void AGameStateBase::GetLifetimeReplicatedProps(
TArray&lt;FLifetimeProperty&gt;&amp; OutLifetimeProps) const
{
FDoRepLifetimeParams Params;
Params.bIsPushBased = true;
//注意 DOREPLIFETIME は PushBased = falseに展開されてしまう！
DOREPLIFETIME( AGameStateBase, bReplicatedHasBegunPlay );
}


# Page. 39

![Page Image](https://bcdn.docswell.com/page/GE8D3KLYED.jpg)

PushModel動作確認
Net.Iris.PrintPushBasedStatuses
LogIris: Display: ################ Start Printing Push-Based Statuses ################
LogIris: Display:
LogIris: Display: MoverNetworkPredictionLiaisonComponent (RefCount: 4) (PushBased: 0)
LogIris: Display:
Printing properties that aren&#039;t push-based:
LogIris: Display:
/Script/NetworkPrediction.NetworkPredictionComponent:NetworkPredictionProxy
LogIris: Display:
/Script/NetworkPrediction.NetworkPredictionComponent:ReplicationProxy_Auto(略)LogIris: Display:
/Script/NetworkPrediction.NetworkPredictionComponent:ReplicationProxy_Simulated
LogIris: Display:
/Script/NetworkPrediction.NetworkPredictionComponent:ReplicationProxy_Replay
LogIris: Display: GameStateBase (RefCount: 1) (PushBased: 0)
LogIris: Display:
Printing properties that aren&#039;t push-based:
LogIris: Display:
/Script/Engine.GameStateBase:SpectatorClass
LogIris: Display:
/Script/Engine.GameStateBase:GameModeClass
LogIris: Display:
/Script/Engine.GameStateBase:ReplicatedWorldTimeSecondsDouble
LogIris: Display:
/Script/Engine.GameStateBase:bReplicatedHasBegunPlay
LogIris: Display: NetCanvasActor (RefCount: 1) (PushBased: 0)
LogIris: Display:
Printing properties that aren&#039;t push-based:
LogIris: Display:
/Script/MultiIris.NetCanvasActor:Tiles
LogIris: Display: GameplayDebuggerCategoryReplicator (RefCount: 4) (PushBased: 1)
LogIris: Display: MultiIrisPlayerController (RefCount: 4) (PushBased: 1)
LogIris: Display: MultiMoverPawn (RefCount: 4) (PushBased: 1)
LogIris: Display: NetCanvasPainterComponent (RefCount: 4) (PushBased: 1)
LogIris: Display: PlayerState (RefCount: 4) (PushBased: 1)
LogIris: Display: NetworkPredictionReplicatedManager (RefCount: 1) (PushBased: 1)
LogIris: Display: WorldDataLayers (RefCount: 1) (PushBased: 1)
LogIris: Display: WorldSettings (RefCount: 1) (PushBased: 1)
LogIris: Display:
LogIris: Display: ################ Stop Printing Push-Based Statuses ################


# Page. 40

![Page Image](https://bcdn.docswell.com/page/LELMVZL97R.jpg)

ListenServer
レガシーレプリケーションでは、各接続先に対する処理負荷が高かっ
たためListenServer動作時に1Tickに処理できるクライアント数に制限
を設けていた
IrisではNetClientTicksPerSecond設定値による送信先クライアント数
上限はなく毎Tick全クライアントにパケットを送信する


# Page. 41

![Page Image](https://bcdn.docswell.com/page/4JMYGVMVJW.jpg)

並列化
[/Script/Engine.Engine]
+IrisNetDriverConﬁgs=(NetDriverName=GameNetDriver, bCanUseIris=true, bCanUseParallelNetConnectionTick=true)
[SystemSettings]
net.iris.AllowParallelNetTick=1
[/Script/OnlineSubsystemUtils.IpNetDriver]
ReplicationSystemConﬁgServer=(bAllowParallelTasks=true, MinConnectionsForParallelTick=2)


# Page. 42

![Page Image](https://bcdn.docswell.com/page/PJR9Z2VW79.jpg)

互換性
●
そのまま動く
○ UPROPERTYのレプリケーション
○ RepNotify
■ net.Iris.UsePrevReceivedStateForOnReps でクライアント側比較の有無を制御
○ PushModel (MARK_PROPERTY_DIRTY)
●
気を付ける
○ RPC
■ 処理順序やタイミングが変化する可能性
■ net.Iris.ExecuteReliableRPCsBeforeApplyState でレプリケートの前か後かを選択
○ NetSerialize &gt; NetSerializer
○ FastArraySerializer &gt; FIrisFastArraySerializerに置換
○ ReplicationGraphはフィルタやプライオリタイザーに移行する
○ Replayはレガシーレプリケーションでしか処理できない


# Page. 43

![Page Image](https://bcdn.docswell.com/page/PEXQ9DZVJX.jpg)

有効化
Irisはエンジンにモジュールとして存在するので、
Irisを使う各モジュールの*.build.csでSetupIrisSupport()を呼び出す
[SystemSettings]
net.Iris.UseIrisReplication=1
net.SubObjects.DefaultUseSubObjectReplicationList=1


# Page. 44

![Page Image](https://bcdn.docswell.com/page/3EK9PX85ED.jpg)

アップデート履歴
Iris導入
IrisNetConﬁg既定化
5.2
5.1
Production-Ready
5.7
5.3
bUseIris=true
デフォルト
5.8
Beta
Runtime/Net/Irisに移動
bUseIris削除
SeamlessTravel対応


# Page. 45

![Page Image](https://bcdn.docswell.com/page/L73WX52175.jpg)

資料
Developing and Launching a New Replication System | Unreal
Fest Orlando 2025
次世代ネットワーク通信実装Irisについて @docswell


# Page. 46

![Page Image](https://bcdn.docswell.com/page/87DK2DZKJG.jpg)

TIPS
“-NewConsole” :
DedicatedServerやヘッドレスクライアントのテスト時に
コマンドラインオプションに追加すると
コンソールコマンド入力欄つきログウィンドウを出せる


# Page. 47

![Page Image](https://bcdn.docswell.com/page/VJPK1XD3E8.jpg)

第 II 部
Mover
次世代移動コンポーネントのネットワーク対応について


# Page. 48

![Page Image](https://bcdn.docswell.com/page/2EVVYL1NEQ.jpg)

Moverとは
特定のクラスに依存しない
モジュラー構造
物理をつかった遊びに対応
操作対象のアクターやコンポーネ
ントに制限がない
モジュールを組み合わせて構成
拡張性に配慮
物理ベースの移動や
剛体とのインタラクション
同期の仕組みを選択式に
マルチスレッドに対応(中)
CMCユーザーフレンドリー
オフラインゲームで複雑な同期
コードを省略できる
一部処理をワーカスレッドにオフ
ロードできるように
基本的なインターフェイスは
(大体)同じものがそろっている
物理同期


# Page. 49

![Page Image](https://bcdn.docswell.com/page/57GL9X25EL.jpg)

Moverのモジュール構造
CMC
(CharacterMovementComponent)
MoverComponent
歴史ある
UBaseMovementMode
キャラクター移動コンポーネント
歩く・落ちる・泳ぐ — 移動の計算
●
●
●
EMovementMode
クラス継承による拡張
組み込み
○ ルートモーション
○ 移動同期
LayeredMove
MovementModiﬁer
Backend Liaison
バックエンドモジュール


# Page. 50

![Page Image](https://bcdn.docswell.com/page/4EQYW8PLJP.jpg)

Backend Liaison
３つのバックエンドから一つを選択
●
●
●
Standalone Liaison
○ ネットワーク同期が不要な場合
○ 一部の処理をワーカースレッドに分散可能
NetworkPrediction Liaison
○ CMCのネットワーク同期システムに近い動作
○ NetworkPredictionPluginの仕組みを利用
ChaosMover Liaison
○ NetworkPhysicsLiaisonから改良&amp;移行
○ 物理シミュレーションベースで動作しているタイトル用
○ 物理界全体のロールバックや再シミュレーション


# Page. 51

![Page Image](https://bcdn.docswell.com/page/KJ4WK2Y571.jpg)

NetworkPredictionPlugin(NPP)
NetworkPredictionManager
NPP
Mover
同期処理を実現するプラグイン
ゲームワールドとは直接繋がっていない
Mover動作時に強制リンクされる
●
●
●
●
同期エラー検出
対象アクターの過去フレームの
ステートの管理
ロールバック時の再シミュレーション
ServerRPC送信
NetworkPredictionLiaison
MovorCompomonent
Title
詳しくは
Plugins/Runtime/NetworkPrediction/readme.txt
を参照
Actor


# Page. 52

![Page Image](https://bcdn.docswell.com/page/LE1YXM627G.jpg)

NPPの同期制御比較


# Page. 53

![Page Image](https://bcdn.docswell.com/page/GEWGN3W2J2.jpg)

補正命令を
Autonomousに返す
入力と移動結果
を送信
パケット毎に
Tickを行う
サーバー側でエ
ラー検出


# Page. 54

![Page Image](https://bcdn.docswell.com/page/47ZL3V54J3.jpg)

エラー検出が
AutonomousClient
に移動
入力のみ送信
Tick時にバッファ
された入力を取得
ForwardPredict用に
Inputも送信


# Page. 55

![Page Image](https://bcdn.docswell.com/page/YJ6WX59GJV.jpg)

CMCとMover+NPPの比較
CMC
Mover+NPP
クライアントからの
送信データフォーマット
入力 + 移動結果
Combineによる合成
入力のみ(多重化)
多重化によりパケロスに強く
サーバーでの処理タイミング
パケットを解析した直後
GameThread内で
バッファされたデータを参照
CMCはクライアントとサーバーの
TickRateの差が大きいとサーバー
負荷が上昇する
検証
サーバー上で
サーバーの移動結果とクライアント
からの移動結果を比較
クライアント上で
ステート(結果)を比較
検証負荷がクライアントへ
補正
サーバーからの結果を適用
ロールバックして
再シミュレーション
SimulateProxyの動作
スムーシング
スムーシング or 前方予測


# Page. 56

![Page Image](https://bcdn.docswell.com/page/GJ5MXYNXJ4.jpg)

NetworkPrediction設定
●
●
●
●
●
●
●
PreferredTickingPolicy :
○
Fixed / Independent
FixedTickFrameRate
○
Fixedの場合のシミュレーションフレームレート
SimulatedProxy Network LOD
○
SimulateProxyの動作
○
Interpolated(単純補間) / ForwardPredict(前方予測)
Enable Fixed Tick Smoothing
(Fixed/Independent)TickInterpolation Buﬀer MS
○
Interpolated時の遅延位置
(Fixed/Independent)TickInputSendCount
○
Inputの多重化数 - パケロス耐性
MaximumRemoteInputFaultLimit
○
Fault(通信途絶)からの復帰判定の入力数閾値
途絶後、バッファがたまるまで前回のキーを使用する
○
InputSendCountがデフォルトで6なので、パケットが
到達したら常にこの条件を満たしてしまう


# Page. 57

![Page Image](https://bcdn.docswell.com/page/9E29XG5Q7R.jpg)

TickingPolicy
Fixed
Independent
備考
Tickのデルタタイム
共通固定デルタタイム
ゲームのデルタタイム
ゲームのフレームレートはどちらも自
由に設定してよい
入力のバッファリング
あり
(遅延として現れる)
なし
遅延なしで適用
出来る限り全クライアントの入力があ
る状態でTickしたいのでバッファリン
グがある
TimeDilation調整
あり
不要
バッファの余裕に応じてクライアント
のTickRateを調整する
SimulateProxyNetworkLOD
Interpolated | ForwardPredict
Interporated
現時点でSimulateProxyは
Interpolated推奨
(公式ドキュメントより)
ロールバック
グループロールバック
単体ロールバック
(すべての ForwardPredictアクター )
RootMotion
AnimRootMotion(単発)
AnimRootMotion(単発)
RootMotionAttribute(ABP出力)
Tickタイミング
マネージャから呼び出される
通常のコンポーネントのTick


# Page. 58

![Page Image](https://bcdn.docswell.com/page/D7Y48VKYEM.jpg)

Enable Fixed Tick Smoothing
Fixedモードでは、シミュレーションTick時間と表示
Tick時間にズレが生じる
ズレた場合にシミュレーションフレーム間の補間を入
れる機能
操作しているキャラクターは前方予測
(ForwardPredict)で動作
np.Smoothing.Disable 1 で一時的に無効化できる
補間はスムーシング対象のMeshComponentに対して
適用されるので、カメラをメッシュの子にアタッチす
る必要があることに注意
Fixed Tick Frame Rate : 10


# Page. 59

![Page Image](https://bcdn.docswell.com/page/VENYQMRRJ8.jpg)

TickingPolicy : Fixed のタイムライン
表示Tick
Fixed Tick
Fixed
Step
Smoothing参照
1固定デルタ分
後方を参照して表示
Fixed
Step
Fixed
Step
Fixed
Step
Fixed
Step
Fixed
Step
Fixed
Step
Fixed
Step
Fixed
Step
Fixed
Step


# Page. 60

![Page Image](https://bcdn.docswell.com/page/Y79PDNMZE3.jpg)

Moverアップデート履歴
StandaloneLiaisonの非同期動作
PhysicsMover &gt; ChaosMover
RootMotionベースの移動
任意平面での移動サポート
Mover導入
Experimental
5.5
5.4
NavWalking
BaseMovement改善
TimeDilation制御
5.6
MovementModiﬁer
5.9~
6.0~
5.7
5.8
ブループリント対応の強化
アニムモンタージュ同期
グループムーブメント
脱Experimentalへ


# Page. 61

![Page Image](https://bcdn.docswell.com/page/G78D3K1Y7D.jpg)

資料
Network Prediction: Replication&#039;s Crystal Ball | Unreal Fest
Bali 2025
Project Titanから学ぶオープンワールドワークフローと次世代
移動コンポーネントMoverの設計 @docswell


# Page. 62

![Page Image](https://bcdn.docswell.com/page/L7LMVZQ9JR.jpg)

まとめ
IrisがUE5.8でプロダクションレディに
特に大規模マルチプレイのパフォーマンスを改善します
MoverはExperimentalステートのままですが
アップデート毎に数多くの改善が盛り込まれ
脱Experimentalに向けて進行中


# Page. 63

![Page Image](https://bcdn.docswell.com/page/4EMYGV1VEW.jpg)

Thank you


