c8.2GAS|GameplayAbility|Ability
大约 6 分钟
Ability
GiveAbility


UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Gameplay Abilities", meta = (DisplayName = "Give Ability", ScriptName = "GiveAbility"))
FGameplayAbilitySpecHandle K2_GiveAbility(TSubclassOf<UGameplayAbility> AbilityClass, int32 Level = 0, int32 InputID = -1);

TryActivateAbility

TryActivateAbility(GameplayAbilitySpec.Handle, bAllowRemoteActivation)

InternalServerTryActivateAbility
void UAbilitySystemComponent::ServerTryActivateAbility_Implementation(FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey)
{
InternalServerTryActivateAbility(Handle, InputPressed, PredictionKey, nullptr);
}
网络权限


可以看到开启了
bAllowRemoteActivation
后客户端上也会执行一次,只不过要注意客户端上没有权限。

没有开启网络预测,会出现网络矫正带来的回滚卡顿
开启网络预测后,极大的优化了回滚
NetExecutionPolicy

NetExecutionPolicy | 本地调用位置 | 远程调用处理逻辑 |
---|---|---|
LocalOnly | 客户端 | 不允许远程激活 |
LocalPredicted | 客户端 | 允许客户端预测 → 发起激活 RPC |
ServerOnly | 服务器 | 客户端请求服务器执行 → CallServerTry... |
ServerInitiated | 服务器 | 客户端无法主动触发,必须由服务器调用 |

AbilityInstancingPolicy|实例化策略

枚举值 | 含义与用途 | 备注 |
---|---|---|
NonInstanced | 能力不创建实例。所有调用共享同一个 Ability 类默认对象(CDO) | 高性能、无状态的能力(如纯粹触发效果);不能调用 EndAbility,不能存储状态 |
InstancedPerActor | 每个拥有该能力的 Actor 创建一个实例,激活时复用该实例 | 支持存储状态、调用 EndAbility、可以被多个激活流程控制;最常用的策略 |
InstancedPerExecution | 每次激活都会创建一个新的 Ability 实例 | 用于需要并发多个激活、每次激活有独立状态的能力(如持续型技能、DOT) |
InstancedPerExecution


InstancedPerActor
CallActivateAbility
void UGameplayAbility::CallActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData)
{
PreActivate(Handle, ActorInfo, ActivationInfo, OnGameplayAbilityEndedDelegate, TriggerEventData);
ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
}
void UGameplayAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
if (TriggerEventData && bHasBlueprintActivateFromEvent)
{
// A Blueprinted ActivateAbility function must call CommitAbility somewhere in its execution chain.
K2_ActivateAbilityFromEvent(*TriggerEventData);
}
else if (bHasBlueprintActivate)
{
// A Blueprinted ActivateAbility function must call CommitAbility somewhere in its execution chain.
K2_ActivateAbility();
}
else if (bHasBlueprintActivateFromEvent)
{
UE_LOG(LogAbilitySystem, Warning, TEXT("Ability %s expects event data but none is being supplied. Use 'Activate Ability' instead of 'Activate Ability From Event' in the Blueprint."), *GetName());
constexpr bool bReplicateEndAbility = false;
constexpr bool bWasCancelled = true;
EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
}
else
{
// Native child classes should override ActivateAbility and call CommitAbility.
// CommitAbility is used to do one last check for spending resources.
// Previous versions of this function called CommitAbility but that prevents the callers
// from knowing the result. Your override should call it and check the result.
// Here is some starter code:
// if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
// {
// constexpr bool bReplicateEndAbility = true;
// constexpr bool bWasCancelled = true;
// EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
// }
}
}
CommitAbility
bool UGameplayAbility::CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags)
{
// Last chance to fail (maybe we no longer have resources to commit since we after we started this ability activation)
if (!CommitCheck(Handle, ActorInfo, ActivationInfo, OptionalRelevantTags))
{
return false;
}
CommitExecute(Handle, ActorInfo, ActivationInfo);
// Fixme: Should we always call this or only if it is implemented? A noop may not hurt but could be bad for perf (storing a HasBlueprintCommit per instance isn't good either)
K2_CommitExecute();
// Broadcast this commitment
ActorInfo->AbilitySystemComponent->NotifyAbilityCommit(this);
return true;
}
CommitAbility可选变体
函数名 | 功能说明 | 默认行为 |
---|---|---|
CommitAbility() | 尝试提交能力,消耗 GE 资源(如消耗蓝量、加 CD)并应用冷却与花费 | 会同时尝试调用 CommitAbilityCost() 和 CommitAbilityCooldown() |
CommitAbilityCooldown() | 单独提交冷却效果(Cooldown GE),不处理消耗资源(如 Mana) | 只提交冷却,不提交消耗 |
CommitAbilityCost() | 单独提交资源消耗(Cost GE),不处理冷却 | 只提交资源消耗,不触发冷却 |

上下文
