mcpField
U
ue-gameplay-abilities

ue-gameplay-abilities

github.com/quodsoler开发4191.2k 次安装4 周前更新
代码仓库

关于 ue-gameplay-abilities

面向 UE 5.8 Gameplay Ability System 开发者的 Skill,介绍能力、效果、属性、任务、标签、复制与 Gameplay Cues,并包含初始化和配置模式。

主要功能

  1. 01Ability System Component 设置
  2. 02能力激活与策略
  3. 03能力任务和事件等待
  4. 04Gameplay 效果与属性
  5. 05标签、复制与 Cues

适用场景

  1. 01实现带消耗或冷却的能力
  2. 02等待动画或 Gameplay 事件
  3. 03应用伤害或限时增益
  4. 04配置 ASC 所有权与复制

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/quodsoler/unreal-engine-skills --skill ue-gameplay-abilities

安装后在 Claude Code 中输入/ue-gameplay-abilities确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ability-task-reference.md
gameplay-effect-reference.md
gas-setup-patterns.md

详细介绍

UE Gameplay Ability System

目标引擎:UE 5.8。以下 API 已根据 5.8 头文件验证;旧形式列在“已弃用 — 请勿使用”下。

GAS 随 GameplayAbilities 插件一起提供(Engine/Plugins/Runtime/GameplayAbilities),已可用于生产环境,并非 Experimental。在 .uproject 中启用该插件,然后将 "GameplayAbilities"、"GameplayTags" 和 "GameplayTasks" 添加到模块 Build.cs 的 PublicDependencyModuleNames 中。本指南涵盖 UAbilitySystemComponent、UGameplayAbility、UGameplayEffect、UAttributeSet、UAbilityTask 和 Gameplay Cues。

上下文

如果 .agents/ue-project-context.md 文件存在,请阅读它(模块名称、约定、已启用的插件、GAS/网络设置)。如果该文件不存在,也请继续。

根据请求和代码库确定相关部分。只有当两种合理的理解会导致不同代码时,才询问。

请求涉及……请参阅
ASC 所属位置、初始化顺序、重生、复制模式ASC 所属关系与初始化
编写能力、激活、消耗、冷却时间、策略Gameplay Abilities
等待蒙太奇、事件、目标选择、计时器、标签查询能力任务
伤害、增益、堆叠、执行、免疫、GE 组件Gameplay Effects
生命值/法力值浮点数、限制范围、属性复制属性集
阻止、授予或取消能力的标签;宽松标签GAS 中的标签
粒子、声音、命中效果、Cue 通知类Gameplay Cues
Cue 扫描路径、全局曲线表、项目配置项目设置

GAS 架构

支柱类头文件用途
组件UAbilitySystemComponentAbilitySystemComponent.h管理能力、效果、属性和标签
能力UGameplayAbilityAbilities/GameplayAbility.h激活时发生的行为
效果UGameplayEffectGameplayEffect.h由数据驱动的属性修改
属性UAttributeSetAttributeSet.h复制的 FGameplayAttributeData 属性
任务UAbilityTaskAbilities/Tasks/AbilityTask.h能力内部的延迟步骤

Gameplay 标签贯穿所有这些部分,用作要求、授予项和阻止条件。

ASC 所属关系与初始化

所属对象适用场景备注
APlayerState联网的玩家角色ASC 在 Pawn 死亡后仍然存在;使用 Mixed 复制模式
APawn / ACharacterAI、单机游戏最简单;AI 使用 Minimal,如果 Pawn 所属的 ASC 需要向所有客户端提供完整数据,则使用 Full

每个拥有或公开 ASC 的 Actor 都要实现 IAbilitySystemInterface:

// MyCharacter.h
#pragma once

#include "GameFramework/Character.h"
#include "AbilitySystemInterface.h"
#include "MyCharacter.generated.h"

class UAbilitySystemComponent;

UCLASS()
class MYGAME_API AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
    GENERATED_BODY()

public:
    AMyCharacter();

    virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "GAS")
    TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
};
// MyCharacter.cpp
#include "MyCharacter.h"
#include "AbilitySystemComponent.h"

AMyCharacter::AMyCharacter()
{
    AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
    AbilitySystemComponent->SetIsReplicated(true);
    AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
}

UAbilitySystemComponent* AMyCharacter::GetAbilitySystemComponent() const
{
    return AbilitySystemComponent;
}

InitAbilityActorInfo(OwnerActor, AvatarActor) 必须在服务器和客户端上都运行。对于 Pawn 所属的 ASC,在 BeginPlay 中以 (this, this) 调用。对于 PlayerState 所属的 ASC,在服务器上的 PossessedBy 和客户端上的 OnRep_PlayerState 中以 (PlayerState, Character) 调用。完整的双路径代码、重生处理和 AI 变体,请参阅 gas-setup-patterns.md。

EGameplayEffectReplicationMode对模拟代理的影响
Minimal不复制 GE;仅提供最少的标签/Cue 数据。适用于 AI 和非玩家 Actor
Mixed向所属连接发送完整 GE,向其他所有连接发送最少数据。适用于玩家角色
Full将每个 GE 复制给每个客户端

Mixed 会向拥有 ASC 所属 Actor 的连接发送完整 GE 数据(GameplayEffect.cpp:5240),因此适用于 PlayerState 所属的 ASC,也适用于 PlayerController 控制 Pawn 后的 Pawn 所属 ASC。选择 Full 而非 Mixed 是带宽方面的取舍,而非正确性问题。Minimal 不适用于玩家所属的 ASC(AbilitySystemComponent.h:83)。有关每种模式的网络带宽开销,请参阅 ue-networking-replication。

Gameplay 能力

// MyFireballAbility.h
#pragma once

#include "Abilities/GameplayAbility.h"
#include "MyFireballAbility.generated.h"

class UGameplayEffect;

UCLASS()
class MYGAME_API UMyFireballAbility : public UGameplayAbility
{
    GENERATED_BODY()

public:
    UMyFireballAbility();

    virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle,
        const FGameplayAbilityActorInfo* ActorInfo,
        const FGameplayTagContainer* SourceTags = nullptr,
        const FGameplayTagContainer* TargetTags = nullptr,
        OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;

    virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
        const FGameplayAbilityActorInfo* ActorInfo,
        const FGameplayAbilityActivationInfo ActivationInfo,
        const FGameplayEventData* TriggerEventData) override;

    virtual void EndAbility(const FGameplayAbilitySpecHandle Handle,
        const FGameplayAbilityActorInfo* ActorInfo,
        const FGameplayAbilityActivationInfo ActivationInfo,
        bool bReplicateEndAbility, bool bWasCancelled) override;

    virtual void CancelAbility(const FGameplayAbilitySpecHandle Handle,
        const FGameplayAbilityActorInfo* ActorInfo,
        const FGameplayAbilityActivationInfo ActivationInfo,
        bool bReplicateCancelAbility) override;

protected:
    UPROPERTY(EditDefaultsOnly, Category = "GAS")
    TSubclassOf<UGameplayEffect> DamageEffect;
};

构造函数设置策略和能力自身的标签:

// MyFireballAbility.cpp
#include "MyFireballAbility.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"

UMyFireballAbility::UMyFireballAbility()
{
    InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
    NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;
    NetSecurityPolicy = EGameplayAbilityNetSecurityPolicy::ClientOrServer;

    FGameplayTagContainer Tags;
    Tags.AddTag(FGameplayTag::RequestGameplayTag(TEXT("Ability.Skill.Fireball")));
    SetAssetTags(Tags);

    ActivationOwnedTags.AddTag(FGameplayTag::RequestGameplayTag(TEXT("Ability.Active.Casting")));
    ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag(TEXT("State.Stunned")));
    CancelAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(TEXT("Ability.Active.Melee")));
}

SetAssetTags 只能在构造函数中调用;使用 GetAssetTags() 读取标签。

枚举值用途
EGameplayAbilityInstancingPolicyInstancedPerActor, InstancedPerExecutionInstancedPerActor 是默认选择;多个实例可能同时运行时使用 InstancedPerExecution
EGameplayAbilityNetExecutionPolicyLocalPredicted, LocalOnly, ServerInitiated, ServerOnly响应迅速的玩家能力使用 LocalPredicted
EGameplayAbilityNetSecurityPolicyClientOrServer, ServerOnlyExecution, ServerOnlyTermination, ServerOnly拒绝应由服务器控制的客户端请求
void UMyFireballAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
    const FGameplayAbilityActorInfo* ActorInfo,
    const FGameplayAbilityActivationInfo ActivationInfo,
    const FGameplayEventData* TriggerEventData)
{
    Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);

    // CommitAbility applies cost and cooldown; it fails if either cannot be paid.
    if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
    {
        EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
        return;
    }

    const FGameplayEffectSpecHandle Spec =
        MakeOutgoingGameplayEffectSpec(DamageEffect, GetAbilityLevel());
    const FGameplayAbilityTargetDataHandle TargetData =
        UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(ActorInfo->AvatarActor.Get());

    ApplyGameplayEffectSpecToTarget(Handle, ActorInfo, ActivationInfo, Spec, TargetData);
    EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
}

如果两部分必须在不同时间发生,则拆分提交:CommitAbilityCost(Handle, ActorInfo, ActivationInfo) 和 CommitAbilityCooldown(Handle, ActorInfo, ActivationInfo, ForceCooldown)——注意,冷却时间重载会额外接收 const bool ForceCooldown。

在实例化的能力中,GetAbilitySystemComponentFromActorInfo_Ensured() 会返回 ASC;如果 Actor 信息尚未设置,它会记录 ensure,而不是导致崩溃。

从服务器授予并激活能力:

const FGameplayAbilitySpecHandle Handle =
    ASC->GiveAbility(FGameplayAbilitySpec(UMyFireballAbility::StaticClass(), 1));

ASC->TryActivateAbility(Handle);
ASC->TryActivateAbilityByClass(UMyFireballAbility::StaticClass());
ASC->TryActivateAbilitiesByTag(
    FGameplayTagContainer(FGameplayTag::RequestGameplayTag(TEXT("Ability.Skill.Fireball"))));
ASC->ClearAbility(Handle);

能力任务

能力任务可让能力跨越多个帧运行。流程始终是:静态工厂 → 绑定委托 → ReadyForActivation()(继承自 UGameplayTask)。任务委托是动态委托,因此每个处理函数都需要 UFUNCTION():

// In the ability's header:
UFUNCTION()
void HandleMontageCompleted();

UFUNCTION()
void HandleMontageInterrupted();
#include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"

UAbilityTask_PlayMontageAndWait* Task =
    UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
        this, NAME_None, AttackMontage, 1.f);
Task->OnCompleted.AddDynamic(this, &UMyFireballAbility::HandleMontageCompleted);
Task->OnInterrupted.AddDynamic(this, &UMyFireballAbility::HandleMontageInterrupted);
Task->ReadyForActivation();
任务等待内容
UAbilityTask_PlayMontageAndWaitUAnimMontage 播放完毕、混出、中断或取消
UAbilityTask_PlayAnimAndWait播放到槽位中的原始 UAnimSequence,用于关联动画层
UAbilityTask_WaitGameplayEvent发送给 ASC 的游戏性事件标签(动画通知、命中注册)
UAbilityTask_WaitDelay固定秒数
UAbilityTask_WaitTargetDataAGameplayAbilityTargetActor 确认目标
UAbilityTask_WaitAttributeChange / ...ChangeThreshold属性发生变化或跨越比较阈值
UAbilityTask_WaitGameplayTagQuery目标的标签满足或不满足 FGameplayTagQuery
UAbilityTask_WaitGameplayTagCountChangedASC 上某个标签的计数发生变化
UAbilityTask_WaitGameplayEffectApplied_Self / _Target匹配标签要求的 GE(或通过 _Query 工厂使用 FGameplayTagQuery)

工厂的完整签名、委托名称、自定义任务模板和任务注意事项,请参阅 ability-task-reference.md。

游戏性效果

EGameplayEffectDurationType行为
Instant对基础值执行一次;触发 PostGameplayEffectExecute
HasDuration在 DurationMagnitude 秒内聚合到当前值
Infinite持续聚合,直到显式移除
const FGameplayEffectContextHandle Ctx = ASC->MakeEffectContext();
const FGameplayEffectSpecHandle Spec =
    ASC->MakeOutgoingSpec(UMyDamageEffect::StaticClass(), Level, Ctx);

Spec.Data->SetSetByCallerMagnitude(
    FGameplayTag::RequestGameplayTag(TEXT("SetByCaller.Damage")), 75.f);

ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get());
ASC->ApplyGameplayEffectSpecToTarget(*Spec.Data.Get(), TargetASC);

ASC->RemoveActiveGameplayEffect(ActiveHandle);
ASC->RemoveActiveGameplayEffectBySourceEffect(UMyDamageEffect::StaticClass(), nullptr);

修饰符运算位于 EGameplayModOp 中(这是一个带命名空间的枚举,因此值的类型为 TEnumAsByte<EGameplayModOp::Type>)。聚合公式为 ((BaseValue + AddBase) * MultiplyAdditive / DivideAdditive * MultiplyCompound) + AddFinal。

值含义
AddBase在其他操作之前加到基础值上
MultiplyAdditive将乘数相加,然后与当前结果相乘
DivideAdditive将除数相加,然后用当前结果除以该值
MultiplyCompound与当前结果相乘,并与其他复合乘数连乘
AddFinal所有乘法完成后再加上
Override替换计算出的值

过去作为 UGameplayEffect 单体属性的行为,现在由 GameplayEffectComponents/ 下的 UGameplayEffectComponent 子类实现。有关堆叠、幅度计算、UGameplayEffectExecutionCalculation、周期性效果、免疫、查询、生命周期委托和完整的组件列表,请参阅 gameplay-effect-reference.md。

属性集

// MyHealthSet.h
#pragma once

#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "MyHealthSet.generated.h"

UCLASS()
class MYGAME_API UMyHealthSet : public UAttributeSet
{
    GENERATED_BODY()

public:
    UMyHealthSet();

    virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
    virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;
    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

    UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Health")
    FGameplayAttributeData Health;
    ATTRIBUTE_ACCESSORS_BASIC(UMyHealthSet, Health)

    UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth, Category = "Health")
    FGameplayAttributeData MaxHealth;
    ATTRIBUTE_ACCESSORS_BASIC(UMyHealthSet, MaxHealth)

protected:
    UFUNCTION()
    void OnRep_Health(const FGameplayAttributeData& OldHealth);

    UFUNCTION()
    void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
};

ATTRIBUTE_ACCESSORS_BASIC 会生成 GetHealthAttribute()、GetHealth()、SetHealth() 和 InitHealth()。需要额外访问器的项目可以定义自己的宏,通过 GAMEPLAYATTRIBUTE_PROPERTY_GETTER、GAMEPLAYATTRIBUTE_VALUE_GETTER、GAMEPLAYATTRIBUTE_VALUE_SETTER 和 GAMEPLAYATTRIBUTE_VALUE_INITTER 链接调用。

每个 OnRep_ 函数体只包含一处 GAMEPLAYATTRIBUTE_REPNOTIFY(UMyHealthSet, Health, OldHealth) 调用,并且每个属性都需要一行 DOREPLIFETIME_CONDITION_NOTIFY(UMyHealthSet, Health, COND_None, REPNOTIFY_Always)。带钳制逻辑的完整 .cpp 文件见 gas-setup-patterns.md。

钩子触发时机用途
PreAttributeChange每次重新计算当前值时仅钳制当前值
PreAttributeBaseChange写入基础值之前(const)钳制基础值
PostGameplayEffectExecute即时 GE 写入基础值后,或周期性 GE 的一个周期写入基础值后死亡、受击反应、游戏事件
PostAttributeChange当前值发生变化后响应派生状态

注册和读取:

// Constructor of the ASC owner — the ASC finds subobject attribute sets automatically:
HealthSet = CreateDefaultSubobject<UMyHealthSet>(TEXT("HealthSet"));

// Runtime, authority only:
UMyHealthSet* NewSet = NewObject<UMyHealthSet>(this);
ASC->AddSpawnedAttribute(NewSet);

const float CurrentHealth = ASC->GetNumericAttribute(UMyHealthSet::GetHealthAttribute());

一个 ASC 可以承载多个 UAttributeSet 子类,但每个类只能有一个实例。

GAS 中的标签

标签定义(原生标签宏、.ini 标签源)、容器匹配和 FGameplayTagQuery 语义属于 ue-gameplay-tags-messaging。GAS 特有的内容如下:

// On the ability CDO (constructor): tags granted while the ability runs, and the gates.
ActivationOwnedTags.AddTag(CastingTag);
ActivationRequiredTags.AddTag(WeaponEquippedTag);
ActivationBlockedTags.AddTag(StunnedTag);
BlockAbilitiesWithTag.AddTag(MeleeTag);
CancelAbilitiesWithTag.AddTag(ChannelTag);

// On the ASC: query and react.
ASC->HasMatchingGameplayTag(StunnedTag);
const FGameplayTagContainer& Owned = ASC->GetOwnedGameplayTags();
ASC->RegisterGameplayTagEvent(StunnedTag, EGameplayTagEventType::NewOrRemoved)
    .AddUObject(this, &AMyCharacter::HandleStunnedTagChanged);

回调声明为 void HandleStunnedTagChanged(const FGameplayTag Tag, int32 NewCount);,无需 UFUNCTION() —— 标签事件是普通的多播委托。

松散标签直接设置,而不是通过 GE 设置。第三个参数决定标签的复制方式:

ASC->AddLooseGameplayTag(StunnedTag);                                              // local only
ASC->AddLooseGameplayTag(BuffedTag, 1, EGameplayTagReplicationState::TagOnly);     // tag to all
ASC->AddLooseGameplayTag(BuffedTag, 1, EGameplayTagReplicationState::CountToOwner);// + count to owner
ASC->RemoveLooseGameplayTag(BuffedTag, 1, EGameplayTagReplicationState::TagOnly);
ASC->SetLooseGameplayTagCount(BuffedTag, 3, EGameplayTagReplicationState::TagAndCountToAll);

EGameplayTagReplicationState 的取值包括:None、SimulatedTagOnly、TagOnly、CountToOwner、TagAndCountToAll。除 None 外,所有取值都必须在服务器上添加。

Gameplay Cues

Cue 仅用于外观效果。标签前缀为 GameplayCue.;GE 可通过其 GameplayCues 数组触发 Cue,也可以由代码直接触发:

ASC->ExecuteGameplayCue(HitCueTag, ASC->MakeEffectContext());   // one-shot
ASC->AddGameplayCue(BuffCueTag);                                // persistent
ASC->RemoveGameplayCue(BuffCueTag);
const bool bActive = ASC->IsGameplayCueActive(BuffCueTag);
类基类重载项用途
UGameplayCueNotify_StaticUObjectOnExecute_Implementation不生成 Actor 的瞬时 Cue
UGameplayCueNotify_BurstUGameplayCueNotify_Static数据驱动的瞬时效果一次性粒子效果/声音,无需编写代码
UGameplayCueNotify_HitImpactUGameplayCueNotify_Static数据驱动的冲击效果按表面类型区分的冲击效果
AGameplayCueNotify_ActorAActorOnActive_/WhileActive_/OnRemove_Implementation需要 Actor 的持续 Cue
AGameplayCueNotify_BurstLatentAGameplayCueNotify_Actor数据驱动的瞬时效果必须生成 Actor 的瞬时 Cue
AGameplayCueNotify_LoopingAGameplayCueNotify_Actor数据驱动的循环效果循环光环和引导效果
// MyHitCue.h
#pragma once

#include "GameplayCueNotify_Static.h"
#include "MyHitCue.generated.h"

UCLASS()
class MYGAME_API UMyHitCue : public UGameplayCueNotify_Static
{
    GENERATED_BODY()

public:
    virtual bool OnExecute_Implementation(AActor* MyTarget,
        const FGameplayCueParameters& Parameters) const override;
};

UGameplayCueManager 会在项目设置中配置的扫描路径下发现 Cue 资源。

项目设置

GAS 配置由 UDeveloperSettings 类提供:UGameplayAbilitiesDeveloperSettings(项目设置 → Gameplay Abilities)。使用 GetDefault<UGameplayAbilitiesDeveloperSettings>() 读取。值得注意的字段包括:GameplayCueNotifyPaths、ReplicateActivationOwnedTags、bAllowGameplayModEvaluationChannels,以及全局曲线/属性表。运行时辅助函数仍由 UAbilitySystemGlobals 提供(GetGameplayCueNotifyPaths()、AddGameplayCueNotifyPath()、GetAttributeSetInitter())。

已弃用 — 请勿使用

请勿发出在 5.8 中使用来源
AGameplayCueNotify_StaticUGameplayCueNotify_Static(一个 UObject)此类从未存在;GameplayCueNotify_Static.h:19
EGameplayModOp::MultiplicativeEGameplayModOp::MultiplyAdditive(旧版别名拼写为 Multiplicitive)GameplayEffectTypes.h:112-148
EGameplayModOp::Additive / DivisionAddBase / DivideAdditive隐藏的向后兼容别名,GameplayEffectTypes.h:141-143
EGameplayAbilityInstancingPolicy::NonInstancedInstancedPerActorAbilities/GameplayAbilityTypes.h:46 中的 UE_DEPRECATED_FORGAME(5.5)
UGameplayAbility::AbilityTagsGetAssetTags() / SetAssetTags()Abilities/GameplayAbility.h:474 中的 UE_DEPRECATED_FORGAME(5.5)
GetAbilitySystemComponentFromActorInfo_Checked()GetAbilitySystemComponentFromActorInfo_Ensured()Abilities/GameplayAbility.h:168 中的 UE_DEPRECATED(5.5)
对 Actor 赋值 NetUpdateFrequencySetNetUpdateFrequency(100.f)GameFramework/Actor.h:903 中的 UE_DEPRECATED(5.5)
UGameplayEffect::StackingType(公开读取)GetStackingType()GameplayEffect.h:2407 中的 UE_DEPRECATED(5.7)
UGameplayEffect::GrantedApplicationImmunityTagsUImmunityGameplayEffectComponentGameplayEffect.h:2379 中的 UE_DEPRECATED(5.3)
AddReplicatedLooseGameplayTagAddLooseGameplayTag(Tag, Count, EGameplayTagReplicationState::CountToOwner)(弃用消息中的替代项;如果客户端不需要计数,则使用 TagOnly)函数已移除(5.8 中没有声明);其底层的 ReplicatedLooseTags 成员在 AbilitySystemComponent.h:1941 中标记为 UE_DEPRECATED(5.7)
FGameplayAbilitySpec::DynamicAbilityTagsGetDynamicSpecSourceTags()GameplayAbilitySpec.h:242 中的 UE_DEPRECATED(5.5)
UAbilitySystemBlueprintLibrary::MakeSpecHandleMakeSpecHandleByClassAbilitySystemBlueprintLibrary.h:249 中的 UE_DEPRECATED(5.5)
UAbilitySystemGlobals 配置成员GetDefault<UGameplayAbilitiesDeveloperSettings>()AbilitySystemGlobals.h 中均标记为 UE_DEPRECATED(5.5)
FGameplayEffectSpec::GetModifierMagnitude(ModifierIdx, bFactorInStackCount)GetModifierMagnitude(int32 ModifierIdx)GameplayEffect.h:1153 中的 UE_DEPRECATED(5.6)
FActiveGameplayEffectHandle(int32)、ResetGlobalHandleMap()、RemoveFromGlobalMap()FActiveGameplayEffectHandle::GenerateNewHandle() 或 GetInstantExecutedHandle();全局映射已移除ActiveGameplayEffectHandle.h:30,66,69 中的 UE_DEPRECATED(5.8)

常见错误

**仅在 Pawn 上实现 IAbilitySystemInterface:**当 ASC 位于 PlayerState 上时,PlayerState 也必须实现该接口,否则 UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent 在获取所有者时会失败。

**只在服务器上调用 InitAbilityActorInfo:**客户端也需要调用。服务器端路径是 PossessedBy,客户端路径是 OnRep_PlayerState。如果不在客户端调用,属性变化委托永远不会在所属客户端触发。

**在初始化前应用 GE:**在运行 InitAbilityActorInfo 前授予能力或应用效果,会导致 ASC 缺少 Actor 信息,且属性集未注册。

在错误的钩子中进行钳制:PreAttributeChange 每次聚合器重新计算时都会触发,因此只能钳制 NewValue。死亡、受击反应和游戏事件应放在 PostGameplayEffectExecute 中处理;它只会在执行时运行(即时 GE 和周期性 Tick)。

**忘记调用 CommitAbility:**能力会运行,但不会支付消耗,也不会开始冷却。

误以为松散标签会复制:AddLooseGameplayTag(Tag) 默认使用 EGameplayTagReplicationState::None。从服务器传入 TagOnly 或 CountToOwner,或者通过 GE 授予标签。

**堆叠数悄然达到上限:**超出 GetStackLimitCount() 的应用会被拒绝,且不会报错。在假定堆叠成功前,先检查 GetCurrentStackCount(Handle)。

**在没有权限检查的情况下于 BeginPlay 中应用启动效果:**后续加入的玩家会再次应用这些效果。使用 HasAuthority() 为每次 GiveAbility 和启动 GE 调用添加权限门控。

**AI 没有 PlayerState:**将 ASC 放在 AI 角色上,调用 InitAbilityActorInfo(this, this) 并设置 Minimal 复制模式。

相关技能

  • ue-gameplay-tags-messaging — 标签定义(原生标签宏、ini 标签源)、容器、FGameplayTagQuery 和游戏消息传递
  • ue-networking-replication — DOREPLIFETIME 变体、RPC、预测键、推送模型
  • ue-animation-system — 动画能力任务驱动的蒙太奇资源、通知和插槽
  • ue-character-movement — 根运动能力任务操控的移动模式
  • ue-cpp-foundations — UPROPERTY/UFUNCTION说明符、委托、TSubclassOf、子系统
  • ue-data-assets-tables — 属性初始化和 FScalableFloat 所依赖的 UCurveTable 和 UDataTable 资源
  • ue-state-trees — 从 State Tree 任务运行能力
  • ue-actor-component-architecture — 组件创建、子对象注册、子对象复制
  • ue-gameplay-framework — PlayerState 和 Pawn 生命周期,以及不使用 GAS 的伤害处理(TakeDamage、UDamageType)
  • ue-input-system — 绑定到能力输入 ID 的 Enhanced Input 动作
  • ue-game-features — 从游戏功能插件授予能力和属性集
  • ue-niagara-effects — Niagara 系统、用户参数、数据接口和数据通道
  • ue-ui-umg-slate — UMG 控件、Slate、Common UI 和 MVVM

评论

支持 Markdown