最小多人接入示例
目标:让一条 UAK 技能在 Listen Server + 1 Client 下正确预测与复制。
UAK 不提供任何网络代码——网络正确性来自"所有副作用都落在 GAS 原语上"。
配套可编译示例:Source/UAKDemo/(工程自带的示例模块,含 ASC / 属性集 / 示例技能),
使用步骤见 03-sample-project.md。
1. ASC 放哪
| 角色 |
建议 |
| 玩家 |
ASC 放 PlayerState(死亡重生后属性/技能保留) |
| AI / 小怪 |
ASC 放 Character(随角色销毁) |
// 玩家 Character:实现 IAbilitySystemInterface 并转发到 PlayerState 的 ASC
UAbilitySystemComponent* AMyCharacter::GetAbilitySystemComponent() const
{
return PlayerState ? PlayerState->FindComponentByClass<UAbilitySystemComponent>() : nullptr;
}
两者都要在 BeginPlay 里 InitAbilityActorInfo(OwnerActor, AvatarActor),
并在 Pawn 被 Possess / 换角色后调用 ASC->RefreshAbilityActorInfo()。
2. 复制模式
ASC->SetReplicationMode(EGameplayEffectReplicationMode::Mixed); // 玩家
ASC->SetReplicationMode(EGameplayEffectReplicationMode::Minimal); // AI
3. 技能配置(UAKGameplayAbility 蓝图/CDO)
| GAS 字段 |
值 |
说明 |
Instancing Policy |
Instanced Per Actor |
UAK 执行器需要实例 |
Net Execution Policy |
Local Predicted |
客户端先跑,服务器校验 |
Net Security Policy |
Client Or Server |
— |
AbilityAsset |
指向一条 UAKAbilityAsset |
UAK 唯一需要的字段 |
4. 授予与激活
ASC->GiveAbility(FGameplayAbilitySpec(MyAKAbilityClass, 1, INDEX_NONE, this));
ASC->TryActivateAbilityByClass(MyAKAbilityClass);
5. 任务的执行端要配对
| 任务 |
建议 NetMode |
ApplyGameplayEffect(伤害/Buff) |
Both(或 ServerOnly 若只要权威结算) |
CollisionQuery |
ServerOnly(目标以服务器为准) |
PlayMontage / SendGameplayCue |
ClientOnly(表现不占服务器) |
SpawnProjectile |
ServerOnly(已在默认值里设好) |
AreaEffect |
ServerOnly(已在默认值里设好) |
6. 常见坑
| 现象 |
原因 |
| 客户端看到伤害又回滚 |
GE 没走预测:确认 Net Execution Policy = Local Predicted,且 GE 的 Duration Policy 与属性复制设置正确 |
| 蒙太奇不复制 |
直接调了 AnimInstance->Montage_Play;要用 UAK 的 PlayMontage 任务(它走 ASC->PlayMontage) |
| 特效只在一端出现 |
Cue 没走 UGameplayCueNotify;不要直接在任务里 Spawn 粒子 |
| 目标不一致 |
查询任务设成了 Both;改成 ServerOnly,并由服务器下发 TargetData |