ASC 挂在哪里:Actor 还是 PlayerState
这是 GAS 多人项目的第一个分水岭问题,答案直接影响断线重连后技能是否还在。
两种挂法的差别
| 挂在 Actor(角色) | 挂在 PlayerState |
|---|---|
| 角色死亡/重生 → ASC 随之销毁与重建 | 角色死亡/重生 → ASC 保留,状态不丢 |
| 实现简单,单体/角色不重生的游戏适合 | 断线重连、换角色、赛季制游戏必须 |
| 网络下 ASC 的 OwnerActor = 角色 | OwnerActor = PlayerState,AvatarActor = 角色 |
选择规则: - 单机 / 不会重生 / 不断线重连 → 挂 Actor(简单直接); - 多人 + 会重生 / 会重连 / 换角色 → 挂 PlayerState。
Lyra 的做法(权威参考)
Epic 官方示例 Lyra 的 ALyraPlayerState 持有 ASC 和 AttributeSet,角色(ALyraCharacter)只是"Avatar(化身)"。角色死了,PlayerState 不动,技能与属性全部保留。这是多人项目的推荐做法。
C++ 侧关键代码:
// PlayerState 头文件
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Abilities")
UAbilitySystemComponent* AbilitySystemComponent;
UPROPERTY()
UMyAttributeSet* AttributeSet;
// 并实现 IAbilitySystemInterface
UAbilitySystemComponent* GetAbilitySystemComponent() const override
{
return AbilitySystemComponent;
}
三个配套概念
ASC 建立时需要配好三个"伙伴":
| 概念 | 作用 | 不配会怎样 |
|---|---|---|
| OwnerActor | ASC 的逻辑拥有者(权限判定) | 权威/预测逻辑错乱 |
| AvatarActor | 视觉化身(地理位置、碰撞参考) | 效果挂在看不见的地方 |
| Replication Mode | 属性同步给客户端的策略 | 网络带宽浪费或状态不同步 |
Replication Mode 三档
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
| 模式 | 同步内容 | 适合 |
|---|---|---|
| Full | 所有 GE 与属性给所有人 | 竞技类(对手状态也要看) |
| Mixed | 游戏性相关 GE 给所有人,UI 相关(如血条)只给自己 | 多数游戏的最佳选择 |
| Minimal | 几乎不同步 GE,只 tags/Cosmetic | 省带宽(如大量小怪) |
经验:主角用 Mixed,大量小怪用 Minimal。这是服务器带宽最直接的优化点之一。
初始化时机(第二个常见坑)
ASC 的初始化要在 OwnerActor 与 AvatarActor 都就绪后做:
void AMyPlayerState::BeginPlay()
{
Super::BeginPlay();
if (AbilitySystemComponent)
{
AbilitySystemComponent->InitAbilityActorInfo(this, GetPawn()); // Owner=this, Avatar=Pawn
}
}
角色重生时也要重新调用 InitAbilityActorInfo(Avatar 变了),否则技能"锁在旧角色身上"。
本章小结
- ASC 挂 Actor 还是 PlayerState:看是否需要"状态跨角色/跨重连保留",多人推荐 PlayerState。
- 伙伴三概念:OwnerActor(权限)、AvatarActor(视觉)、Replication Mode(同步策略)。
- 角色重生 / 断线重连后要重新 InitAbilityActorInfo。
