🎮 GAS系统在多人游戏中的设置差异与初始化时机

一、概述

**多人游戏(Networked Game)**中,由于存在服务器与多个客户端的结构,GAS 的使用必须区分不同对象在运行时的职责和行为。


二、GAS核心对象与角色差异

对象名称 功能说明
Owner Actor GAS组件的拥有者(通常为PlayerState,便于跨控制器持久化)。
Avatar Actor 能力的执行者(通常为Character或Pawn)。
Controller 控制角色的输入源(客户端中为PlayerController)。
Server(Authority) 权威角色,处理所有真实逻辑、能力应用、属性变化。
Client 接收结果并本地预测显示,仅可请求、不能决定游戏状态。

三、各端差异汇总

1. 能力激活与同步

操作内容 服务器 本地客户端 远程客户端
激活Ability 权威执行 预测激活 不能激活
应用GameplayEffect 执行并广播 预测申请 被动接收
属性变化(如HP) 计算更新 仅接受同步 被动同步
动画等表现 播放实际动画 播放预测动画 接收并展示

四、初始化流程详解

1. 关键函数

  • InitAbilityActorInfo(OwnerActor, AvatarActor)
    初始化 GAS,使其知道“谁拥有”与“谁在表现能力”。

  • GiveAbility / ApplyGameplayEffectToSelf
    授予技能与初始属性,仅应由服务器执行。

  • BindAbilityActivationToInputComponent
    客户端绑定输入与Ability激活。


2. 初始化顺序与执行位置

步骤 函数 执行端 说明
1 构造 / BeginPlay 所有 创建AbilitySystemComponent指针
2 PossessedBy 服务器 初始化 GAS + 授予能力和属性
3 OnRep_PlayerState 客户端 重新初始化 GAS 以同步服务器信息
4 SetupPlayerInputComponent 本地客户端 绑定输入到Ability

3. 推荐实现结构(Character类)

// 服务器端:控制器接管后初始化 GAS
void AMyCharacter::PossessedBy(AController* NewController)
{
    Super::PossessedBy(NewController);
    AbilitySystemComponent->InitAbilityActorInfo(GetPlayerState(), this);
    GrantDefaultAbilities(); // 授予能力和属性
}

// 客户端:同步PlayerState后初始化 GAS
void AMyCharacter::OnRep_PlayerState()
{
    Super::OnRep_PlayerState();
    AbilitySystemComponent->InitAbilityActorInfo(GetPlayerState(), this);
}

// 输入绑定(本地控制客户端)
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);
    if (IsLocallyControlled())
    {
        AbilitySystemComponent->BindAbilityActivationToInputComponent(
            InputComponent,
            FGameplayAbilityInputBinds("Confirm", "Cancel", "EAbilityInputID")
        );
    }
}