02 - Ability System Component
本文主要说明了UE5中Gameplay技能系统(Gameplay Ability System, GAS)中有关 Ability System Component(ASC)的相关内容。
概述
技能系统组件(UAbilitySystemComponent,简称ASC)是Actor和GAS之间的桥梁。Actor需要拥有自己的技能系统组件,或访问PlayerState或Pawn上的技能系统组件,才能与GAS进行互动。
要让Actor参与到GAS中,需要让它重写实现IAbilitySystemInterface接口中的GetAbilitySystemComponent()函数。这是因为在部分情况下会使用其他Actor的ASC,如果不实现该函数就会让获取流程变复杂。
基础知识
Owner Actor和Avatar Actor
ASC的所有者有Owner Actor和Avatar Actor之分:
- Owner Actor:是ASC的逻辑所有者,也就是实际拥有该ASC的Actor;
- Avatar Actor:是ASC的物理表现载体,也就是实际执行Gameplay Ability等特性的Actor;
这两个Actor将ASC的所有权和表现层进行分离,方便开发者进行相关开发。
通过执行InitAbilityActorInfo()函数以初始化这两个Actor,一般来说,执行该函数的时机如下:
- 对于玩家控制的角色,在设置好Controller的所有权后:
- ASC的Owner Actor是Pawn:服务端在
PossessedBy()中执行;客户端在AcknowledgePossession()中执行; - ASC的Owner Actor是PlayerState:服务端在
PossessedBy()中执行;客户端在OnRep_PlayerState()中执行;
- ASC的Owner Actor是Pawn:服务端在
- 对于AI控制的角色,如果ASC的Owner Actor是Pawn,则在
BeginPlay()中执行即可;
例如在Aura项目中,玩家的ASC在AAuraPlayerState类中被初始化,在AAuraCharacter::InitAbilitySystem()中通过IAbilitySystemInterface接口中的GetAbilitySystemComponent()函数被获取,并设置这两个Actor:
AuraCharacter.cpp点击展开/折叠代码
void AAuraCharacter::InitAbilitySystem()
{
AAuraPlayerState* AuraPlayerState = GetPlayerState<AAuraPlayerState>();
checkf(AuraPlayerState, TEXT("Can't get AuraPlayerState !!!"));
AuraPlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(AuraPlayerState, this);
// ...
}
网络同步
要想启用ASC的网络同步,需要在初始化ASC时执行SetIsReplicated(true)。
Replication Mode
执行SetIsReplicated(true)后,还需要执行SetReplicationMode()以设置ASC的网络同步模式。ASC的网络同步模式主要有如下三种:
- Full:适用于极少数玩家场景(单机/局域网), Gameplay Effects会被同步到所有客户端中;
- Mixed:适用于多人游戏, 玩家控制的Actor, Gameplay Effects只会被同步到玩家拥有的客户端中,Gameplay Cues 和 Gameplay Tags 会被同步到所有客户端中;
- Minimal:适用于多人游戏, AI控制的Actor, Gameplay Effects不会被同步, Gameplay Cues 和 Gameplay Tags 会被同步到所有客户端中;
此外,对于Mixed模式,它的OwnerActor必须是Controller。
常用操作
以下内容是关于ASC的常用操作,笔者会根据自己使用情况进行更新。
GE相关
绑定GE施加时的回调函数
ASC通过定义若干委托以允许我们绑定GE施加时的回调函数:
AbilitySystemComponent.h点击展开/折叠代码
/** Delegate for when an effect is applied */
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnGameplayEffectAppliedDelegate, UAbilitySystemComponent*, const FGameplayEffectSpec&, FActiveGameplayEffectHandle);
/** Called on server whenever a GE is applied to self. This includes instant and duration based GEs. */
FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToSelf;
/** Called on server whenever a GE is applied to someone else. This includes instant and duration based GEs. */
FOnGameplayEffectAppliedDelegate OnGameplayEffectAppliedDelegateToTarget;
/** Called on both client and server whenever a duration based GE is added (E.g., instant GEs do not trigger this). */
FOnGameplayEffectAppliedDelegate OnActiveGameplayEffectAddedDelegateToSelf;
/** Called on server whenever a periodic GE executes on self */
FOnGameplayEffectAppliedDelegate OnPeriodicGameplayEffectExecuteDelegateOnSelf;
/** Called on server whenever a periodic GE executes on target */
FOnGameplayEffectAppliedDelegate OnPeriodicGameplayEffectExecuteDelegateOnTarget;
我们需要根据情况和GE的类型选择对应的委托,然后创建相关回调函数并绑定。