🔄 Iris 网络复制系统技术分析 - 第零部分:概念对照表

💡 0.1 为什么需要概念对照?
如果你已经熟悉 UE 传统的网络复制系统(基于 Actor Channel 的架构),那么理解 Iris 会更加容易。Iris 重新设计了很多概念,但核心目标是一致的:高效地同步游戏状态。
本章提供一个"翻译表",帮助你快速建立新旧概念之间的对应关系。
🎯 类比:就像学习一门新语言时,先建立词汇对照表,再学习语法会事半功倍。
📊 0.2 核心概念对照表
🏗️ 架构层面对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 复制系统的核心管理器,Iris 中 ReplicationSystem 承担了更多职责 |
|
| 底层连接仍使用 NetConnection,Iris 用 ConnectionId 标识 |
| ❌ 已移除 | Iris 不再使用 Channel 概念,采用扁平化的对象管理 |
|
| 网络对象标识符,Iris 使用更紧凑的句柄设计 |
|
| 网络对象的唯一标识 |
🎯 对象管理对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 标记对象是否复制 → 拥有有效句柄表示正在复制 |
|
| 静态优先级 + 可替换的优先级策略 |
|
| 网络更新频率 → 轮询频率 |
|
| 裁剪距离 + 空间网格过滤 |
|
| 通过过滤器配置实现始终相关 |
|
| 所有者连接 + 连接过滤 |
|
| 依赖对象调度提示 |
|
| 组件作为子对象参与复制 |
|
| 子对象复制参数更丰富 |
🔍 过滤与相关性对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 相关性判断 → 过滤器系统 |
|
| 相关性延迟 → 滞后更新器 |
距离相关性 |
| 空间网格过滤器 |
|
| 网络视图/观察目标 |
|
| 视图位置 |
|
| 视图方向 |
|
| 内部视图 |
⚡ 优先级对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 优先级计算 → 优先级器系统 |
距离优先级 |
| 球形距离优先级 |
所有者优先级加成 |
| 所有者加成优先级器 |
|
| 优先级累积机制 |
| 内部时间戳管理 | 上次更新时间由系统内部管理 |
📦 序列化对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 通用归档 → 专用比特流 |
|
| 自定义序列化 → 序列化器系统 |
|
| 属性注册 → 状态描述符 |
|
| 条件复制 |
|
| 预复制回调 |
|
| 属性变化通知 |
|
| 属性变化回调 |
🔄 脏数据检测对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
属性比较 |
| 每帧比较 → 轮询 + 推送模型 |
|
| Push Model 脏标记宏 |
|
| 变化追踪 → 脏对象追踪器 |
|
| 变化列表 → 变化掩码 |
😴 休眠对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 休眠模式 → 休眠接口 |
|
| 完全休眠 |
| 通过 | 部分休眠 |
|
| 强制唤醒 |
|
| 强制网络更新 |
📡 RPC 对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
|
| 服务器 RPC |
|
| 客户端 RPC |
|
| 多播 RPC |
|
| 可靠性标志 |
|
| 不可靠性标志 |
🌐 关卡流送对照
传统系统概念 | Iris 概念 | 说明 |
|---|---|---|
| 关卡组 ( | 关卡可寻址对象 → 关卡组 |
关卡可见性 |
| 关卡可见性 → 组过滤状态 |
|
| 流送关卡加载 → 包含过滤组 |
🏗️ 0.3 架构对照图解
传统系统架构
PLAINTEXT
┌─────────────────────────────────────────────────────────────┐
│ AActor │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ bReplicates │ │ NetPriority │ │ IsNetRelevantFor() │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UNetDriver │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ServerReplicateActors() │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 遍历所有 │→ │ 相关性 │→ │ 优先级 │ │ │
│ │ │ Actor │ │ 检查 │ │ 排序 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UActorChannel │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ ReplicateActor │ │ Serialize │ │ Send to Connection │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UNetConnection │
└─────────────────────────────────────────────────────────────┘Iris 架构
PLAINTEXT
┌─────────────────────────────────────────────────────────────┐
│ AActor │
│ ┌────────────────────┐ ┌────────────────────────────────┐ │
│ │ UPROPERTY(Replicated) │ │ GetLifetimeReplicatedProps() │ │
│ └────────────────────┘ └────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UEngineReplicationBridge │
│ ┌─────────────────┐ ┌─────────────────────────────────┐ │
│ │ StartReplicating│ │ 管理 Actor/Component 生命周期 │ │
│ │ Actor() │ │ │ │
│ └─────────────────┘ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UReplicationSystem │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 过滤 │ │ 优先级 │ │ 序列化 │ │ RPC │ │
│ │ Filter │ │Prioritizer│ │Serializer│ │ Handler │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ ┌───────────────────────────┴───────────────────────────┐ │
│ │ DataStream │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │ │
│ │ │ ReplicationWriter │ │ ReplicationReader │ │ 增量压缩 │ │ │
│ │ └──────────────┘ └──────────────┘ └────────────┘ │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UNetConnection │
└─────────────────────────────────────────────────────────────┘🔀 0.4 关键差异说明
1️⃣ Channel 概念的移除
传统系统:
CPP
// 每个复制 Actor 都有一个 ActorChannel
UActorChannel* Channel = Connection->FindActorChannel(Actor);
if (Channel)
{
Channel->ReplicateActor();
}Iris:
CPP
// 没有 Channel 概念,直接通过 ReplicationSystem 管理
FNetRefHandle Handle = Bridge->GetReplicatedRefHandle(Actor);
// 系统内部统一管理所有对象的复制💡 为什么移除:Channel 是一对一绑定模式,Iris 采用扁平化管理,所有对象由 ReplicationSystem 统一调度,更利于批量处理和并行化。
2️⃣ 相关性检查的变化
传统系统:
CPP
// 每个 Actor 实现自己的相关性检查(虚函数)bool AActor::IsNetRelevantFor(const AActor* RealViewer,
const AActor* ViewTarget,
const FVector& SrcLocation) const{
// 自定义相关性逻辑
return (GetDistanceTo(ViewTarget) < NetCullDistanceSquared);
}Iris:
CPP
// 使用可配置的过滤器(策略模式)UCLASS()
class UMyCustomFilter : public UNetObjectFilter
{
virtual void Filter(FNetObjectFilteringParams& Params) override
{
// 批量处理所有对象的过滤
for (uint32 ObjectIdx : Params.ObjectIndices)
{
// 过滤逻辑
}
}
};💡 为什么改变:虚函数调用无法批量优化,Iris 的过滤器可以一次处理多个对象,且过滤策略可配置替换。
3️⃣ 优先级计算的变化
传统系统:
CPP
// 在 Actor 中直接设置优先级属性
AActor::NetPriority = 3.0f;
// 或重写 GetNetPriorityfloat AActor::GetNetPriority(const FVector& ViewPos,
const FVector& ViewDir,
AActor* Viewer, ...){
return NetPriority * DistanceFactor;
}Iris:
CPP
// 使用可替换的优先级器
ReplicationSystem->SetStaticPriority(Handle, 3.0f);
ReplicationSystem->SetPrioritizer(Handle, SphereWithOwnerBoostPrioritizerHandle);
// 优先级器内部批量计算void USphereNetObjectPrioritizer::Prioritize(FNetObjectPrioritizationParams& Params){
// SIMD 优化的批量优先级计算
}4️⃣ 脏数据检测的优化
传统系统:
CPP
// 每帧比较所有复制属性void UNetDriver::ServerReplicateActors(){
for (AActor* Actor : ReplicatedActors)
{
// 逐个属性比较,开销大
CompareProperties(Actor);
}
}Iris:
CPP
// 使用 Push Model,只在属性变化时标记void AMyActor::SetHealth(float NewHealth){
Health = NewHealth;
IRIS_MARK_PROPERTY_DIRTY(this, Health); // 主动标脏
}
// 轮询时只检查已标脏的对象void ObjectPoller::Poll(){
for (uint32 ObjectIdx : DirtyObjects)
{
// 只处理脏对象
}
}5️⃣ 序列化的专用化
传统系统:
CPP
// 使用通用的 FArchivebool NetSerialize(FArchive& Ar, ...){
Ar << Value; // 通用序列化
}Iris:
CPP
// 使用专用的 NetSerializer,支持量化和增量压缩struct FMyNetSerializer
{
static void Serialize(FNetSerializationContext& Context, const FNetSerializeArgs& Args)
{
// 专用量化序列化
uint16 QuantizedValue = FMath::RoundToInt(SourceValue * 100.0f);
Writer.WriteBits(QuantizedValue, 16);
}
};📋 0.5 迁移映射速查表
从传统代码迁移到 Iris
传统代码 | Iris 等效代码 |
|---|---|
|
|
| 配置 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 实现自定义 |
| 实现自定义 |
|
|
🎯 0.6 概念理解检查清单
在开始深入学习 Iris 之前,确保你理解以下对应关系:
ReplicationSystem 是核心调度器,类似传统的 NetDriver 但职责更集中
FNetRefHandle 是对象标识,取代 FNetGUID
Filter 系统取代
IsNetRelevantFor()虚函数Prioritizer 系统取代
GetNetPriority()虚函数Push Model 是推荐的脏数据检测方式
没有 Channel,所有对象由 ReplicationSystem 统一管理
NetSerializer 提供专用的量化序列化,优于通用 FArchive
📝 小结
第零部分建立了 Iris 与传统 UE 网络系统之间的概念映射:
🏗️ 架构层面:ReplicationSystem 取代了 NetDriver + ActorChannel 的组合
🎯 对象管理:FNetRefHandle 取代 FNetGUID,扁平化管理取代 Channel 模式
🔍 过滤系统:可配置的 Filter 取代
IsNetRelevantFor()虚函数⚡ 优先级系统:可替换的 Prioritizer 取代
GetNetPriority()虚函数📦 序列化:专用 NetSerializer 取代通用 FArchive
🔄 脏数据检测:Push Model + Poll 取代每帧全量比较
💡 核心思想:Iris 将"每个对象自己实现"的模式,改为"系统统一调度 + 策略可替换"的模式,从而获得更好的批量处理能力和性能优化空间。
下一部分将深入介绍 Iris 的系统概述与架构设计。
本文档基于 Unreal Engine 5.5.0 Iris 源代码分析(源码目录:Engine/Source/Runtime/Experimental/Iris/)
