当前位置: 首页 > ai >正文

虚幻GAS底层原理解剖十 (网络)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、能力激活的RPC与预测
  • 二、目标数据(Targeting)同步
  • 三、GameplayEffect(GE)复制与模式
  • 四、属性(Attribute)复制
  • 五、标签(GameplayTag)复制
  • 六、GameplayCue(表现)复制与预测
  • 七、能力任务(AbilityTask)与动画蒙太奇
  • 八、复制可见性:Owner vs Non-Owner
  • 九、关键代码片段(常用骨架)
    • 1. 预测窗口 + 激活
    • 2. 服务器端应用GE(权威)
    • 3. 目标数据回传(客户端→服务器)
    • 4. 属性Rep
    • 5. 标签(GameplayTag)复制
    • 6. GameplayCue(表现)复制与预测
    • 7. 能力任务(AbilityTask)与动画蒙太奇
    • 8. 复制可见性:Owner vs Non-Owner
    • 9. 关键代码片段(常用骨架)
  • 十、带宽与一致性优化要点
  • 十一、常见坑位清单
  • 十二、心智模型总结


前言

GAS遵循UE网络范式:服务器权威(Authoritative Server)、客户端预测(Client Prediction)、差量复制(Delta Replication)。
主数据的真正生效都在服务器,客户端为提升手感可本地预演,若被服务器否决再回滚。

Client 输入 → 客户端预测执行 → 发送RPC请求↓                      ↑预测Key标记            服务器授权/否决↓                      ↑服务器结果复制 → 客户端对齐/回滚

一、能力激活的RPC与预测

激活流程(关键调用链)

  1. 客户端:ASC->TryActivateAbility(…) →(若需要)发起 ServerTryActivateAbility RPC
  2. 服务器:校验标签/冷却/资源 → 调 Ability->ActivateAbility()
  3. 客户端:本地开启预测窗口,先行播放动画/发特效/甚至临时改属性

FScopedPredictionWindow Prediction(ASC, /*bShouldGenerateNewKey*/ true);
ASC->TryActivateAbility(Handle);
// Within window: predicted tasks/GE/cues..

PredictionKey:为本次预测生成唯一标识,服务器确认时回传;若否决,客户端用这个键撤销对应预测操作(如移除已播的GameplayCue/还原属性)。

预测失败回滚

  1. 常见来源:资源不足、被控制、冷却中、目标非法
  2. GAS内部基于 PredictionKey 跟踪“预测生成物”,服务器否决→客户端自动撤销
  3. 你只需确保使用预测安全的API(下面各模块会标注)

二、目标数据(Targeting)同步

目标数据通过 UAbilityTask_WaitTargetData 协调,同步接口核心是:

  1. 客户端完成选取 → ASC->ServerSetReplicatedTargetData(Handle, PredictionKey, TargetData, …)
  2. 服务器复核合法性(距离、可见性、阵营等)→ 合法则继续;否则拒绝

数据承载体:FGameplayAbilityTargetDataHandle(结构体+序列化),非UObject,体量小,可预测。
典型用法:射线/地面点击/范围选择在本地即时反馈 → 服务器二次确认。

三、GameplayEffect(GE)复制与模式

激活中的GE存放于 FActiveGameplayEffectsContainer,复制用 Fast Array Serializer(只传增量:新增/更新/移除),并按复制模式裁剪信息量:

UENUM()
enum class EGameplayEffectReplicationMode : uint8 {Minimal,  // 非Owner几乎仅看到GameplayCue和必要最小信息Mixed,    // Owner多信息,旁观者最小信息(常用)Full      // 全量复制给所有人(带宽最高)
};
  1. Minimal/Mixed:减少对非Owner客户端的带宽;Owner仍能拿到完整的Spec(如剩余时间、堆叠等)

  2. GE本体(UGameplayEffect)不复制,复制的是运行时Spec与状态(轻量结构体)

预测GE:客户端可在预测窗口内本地ApplyGameplayEffectSpecToSelf(有的项目封装了预测友好的版本),服务器确认后对齐;否决则回滚。

四、属性(Attribute)复制

  1. 属性字段(FGameplayAttributeData)使用NetDeltaSerialize + OnRep_XXX:

  2. 只有变更才复制(差量)

推荐做法:

UPROPERTY(ReplicatedUsing=OnRep_Health)
FGameplayAttributeData Health;
UFUNCTION() void OnRep_Health(const FGameplayAttributeData& OldValue);
  1. 不要直接改变量,一律通过 GE/ASC API 改(否则不会触发聚合/回调/复制)

聚合与快照:计算走 FAggregator(Base/Add/Mult/Override叠加),GE应用时可捕获瞬时快照,保证确定性;复制传值而非引用,带宽更省。

五、标签(GameplayTag)复制

ASC维护OwnedTags/TagCount容器:

  1. 由GE授予/移除或ASC直接添加的“松散标签”
  2. 用紧凑格式与FastArray复制“计数变化”
  3. 常用:Status.Stunned 阻断激活、Cooldown.X 冷却中;
    非Owner只需知道“是否被晕/在冷却”,无需所有细节 → 模式裁剪即可省带宽

六、GameplayCue(表现)复制与预测

Cue是“表现层信号”(特效/音效/震屏),复制极度精简:

  1. 只发CueTag + 少量参数(FGameplayCueParameters),客户端本地查表播放FX
  2. 支持预测Cue(先播后判),服务器否决→自动终止/回滚
  3. 建议把重资产交给本地:少传数据,多本地决定

七、能力任务(AbilityTask)与动画蒙太奇

许多Task内置网络/预测处理(如 PlayMontageAndWait、WaitTargetData):

  1. 客户端本地播蒙太奇(预测),ASC有一套Montage同步RPC(如播放、停止、播放速率、BlendOut),最终以服务器为准
  2. RootMotion/位移技能:尽量走角色移动预测通道(UE运动分层已做优化),避免大块数据自己复制

八、复制可见性:Owner vs Non-Owner

GAS大量使用OwnerOnly/Everyone/SkipOwner等复制条件:

  1. Owner得到完整状态(UI/操作需要)
  2. 其他客户端仅获最小必要(例如只知道对方“在中毒”和大致剩余时长,或仅视觉Cue)
  3. 配合 EGameplayEffectReplicationMode::Mixed,是实战最常用的带宽折中

九、关键代码片段(常用骨架)

1. 预测窗口 + 激活

if (ASC->CanActivateAbility(Handle)) {FScopedPredictionWindow Pred(ASC, true);ASC->TryActivateAbility(Handle);
}

2. 服务器端应用GE(权威)

FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(GEClass, Level, ASC->MakeEffectContext());
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get()); // Server authoritative

3. 目标数据回传(客户端→服务器)

// Task 内部:Client确定目标后
ASC->ServerSetReplicatedTargetData(Handle, PredKey, TargetData, ApplicationTag, ASC->ScopedPredictionKey);

4. 属性Rep

void UMyAttrSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const {DOREPLIFETIME_CONDITION_NOTIFY(UMyAttrSet, Health, COND_None, REPNOTIFY_Always);
}

5. 标签(GameplayTag)复制

ASC维护OwnedTags/TagCount容器:

  1. 由GE授予/移除或ASC直接添加的“松散标签”
  2. 用紧凑格式与FastArray复制“计数变化”
  3. 常用:Status.Stunned 阻断激活、Cooldown.X 冷却中;
    非Owner只需知道“是否被晕/在冷却”,无需所有细节 → 模式裁剪即可省带宽

6. GameplayCue(表现)复制与预测

Cue是“表现层信号”(特效/音效/震屏),复制极度精简:

  1. 只发CueTag + 少量参数(FGameplayCueParameters),客户端本地查表播放FX
  2. 支持预测Cue(先播后判),服务器否决→自动终止/回滚
  3. 建议把重资产交给本地:少传数据,多本地决定

7. 能力任务(AbilityTask)与动画蒙太奇

许多Task内置网络/预测处理(如 PlayMontageAndWait、WaitTargetData):

  1. 客户端本地播蒙太奇(预测),ASC有一套Montage同步RPC(如播放、停止、播放速率、BlendOut),最终以服务器为准
  2. RootMotion/位移技能:尽量走角色移动预测通道(UE运动分层已做优化),避免大块数据自己复制

8. 复制可见性:Owner vs Non-Owner

GAS大量使用OwnerOnly/Everyone/SkipOwner等复制条件:

  1. Owner得到完整状态(UI/操作需要)
  2. 其他客户端仅获最小必要(例如只知道对方“在中毒”和大致剩余时长,或仅视觉Cue)
  3. 配合 EGameplayEffectReplicationMode::Mixed,是实战最常用的带宽折中

9. 关键代码片段(常用骨架)

  1. 预测窗口 + 激活
if (ASC->CanActivateAbility(Handle)) {FScopedPredictionWindow Pred(ASC, true);ASC->TryActivateAbility(Handle);
}
  1. 服务器端应用GE(权威)
FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(GEClass, Level, ASC->MakeEffectContext());
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get()); // Server authoritative
  1. 目标数据回传(客户端→服务器)
// Task 内部:Client确定目标后
ASC->ServerSetReplicatedTargetData(Handle, PredKey, TargetData, ApplicationTag, ASC->ScopedPredictionKey);
  1. 属性Rep
void UMyAttrSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const {DOREPLIFETIME_CONDITION_NOTIFY(UMyAttrSet, Health, COND_None, REPNOTIFY_Always);
}

十、带宽与一致性优化要点

  1. 选择合适复制模式:Mixed 多数项目够用;PvP观战密集可用 Minimal
  2. 减少非Owner信息:只让旁观者看到“结果/表现”,不看内部细节
  3. Cue轻量化:尽量用Tag驱动本地FX,参数只传必要的(位置/归属/标量)
  4. 分层预测:移动→UE Movement;技能→GAS预测;动画→Montage同步;不要自造大包
  5. 避免直接改属性:必须通过GE/ASC,才能触发聚合、Rep、UI回调
  6. Target合法性在服端再判:客户端只做手感,不要信任它
  7. 合理使用冷却/成本GE而非自写RPC判断(数据驱动 + 自动复制)

十一、常见坑位清单

  1. 忘了 InitAbilityActorInfo(Owner, Avatar) → 能力拿不到ActorInfo,网络异常
  2. Attribute未 ReplicatedUsing 或没 DOREPLIFETIME → 客户端UI不更新
  3. 直接写 Health.SetCurrentValue() → 不走GE管线,无回调无复制
  4. 用 Full 模式在多人战斗里 → 带宽爆表
  5. 预测API与普通API混用不当 → 回滚残留(务必在 FScopedPredictionWindow 内做预测)
  6. 目标数据未做服务器合法性校验 → 作弊风险、状态错乱

十二、心智模型总结

  1. 服权:一切“结果”以服务器为准
  2. 预测:客户端先演,键控回滚
  3. 差量:只传变化,少传大对象
  4. 裁剪:Owner全量、他人最少
  5. 数据驱动:GE/Tag/Attr/Cue各司其职,自动带来复制与一致性
http://www.xdnf.cn/news/17503.html

相关文章:

  • 深度剖析 Linux 信号:从基础概念到高级应用,全面解析其在进程管理与系统交互中的核心作用与底层运行机制
  • Orange的运维学习日记--39.Nginx详解与服务部署
  • 【liunx】web高可用---nginx
  • GSON 框架下百度天气 JSON 数据转 JavaBean 的实战攻略
  • ZooKeeper和Reids做分布式锁的区别?
  • Notepad--:国产跨平台文本编辑器,Notepad++ 的理想替代方案
  • 车载软件架构 --- 车辆量产后怎么刷写Flash Bootloader
  • 【数据结构入门】二叉树(1)
  • Redis7 GEO功能介绍与电商场景案例解析
  • Android模块化架构深度解析:从设计到实践
  • HTML5中华美食网站源码
  • (Arxiv-2025)Phantom-Data:迈向通用的主体一致性视频生成数据集
  • LangChain框架之 invoke() 方法
  • 【SpringBoot】02 基础入门-什么是Spring Boot?:Spring与SpringBoot
  • CLIP在文生图模型中的应用
  • Unity笔记(五)知识补充——场景切换、退出游戏、鼠标隐藏锁定、随机数、委托
  • redis笔记(二)
  • 深入解析游戏引擎(OGRE引擎)通用属性系统:基于Any类的类型安全动态属性设计
  • 《深度剖析前端框架中错误边界:异常处理的基石与进阶》
  • Rust 实战五 | 配置 Tauri 应用图标及解决 exe 被识别为威胁的问题
  • 麒麟系统使用-PATH设置
  • 【96页PPT】华为IPD流程管理详细版(附下载方式)
  • 34-Hive SQL DML语法之查询数据-3
  • 游戏盾是什么?
  • Vibe Coding 自然语言驱动 AI 编程方式
  • 在Linux中部署tomcat
  • Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin
  • 自然语言处理实战:用LSTM打造武侠小说生成器
  • GraalVM !拥抱云原生的 JVM
  • Python 的浅拷贝 vs 深拷贝(含嵌套可变对象示例与踩坑场景)