这一篇文章主要是对GA的源码定义文件的解析,方便后续学习对GA内部的内容做一个了解,而不是去学习GA的实现。
首先对源码注释进行一个了解
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"// 包含核心模块的最小定义
#include "UObject/ObjectMacros.h"// 包含UObject的宏定义
#include "UObject/Object.h"// 包含UObject类的定义
#include "Templates/SubclassOf.h"// 包含子类模板的定义
#include "GameplayTagContainer.h"// 包含游戏标签容器的定义
#include "GameplayEffectTypes.h" // 包含游戏效果类型的声明
#include "GameplayAbilitySpec.h"// 包含游戏技能实例的定义
#include "GameplayEffect.h"// 包含游戏效果的定义
#include "Abilities/GameplayAbilityTypes.h"// 包含游戏技能类型的声明
#include "GameplayTaskOwnerInterface.h" // 包含游戏技能任务所有者接口的定义
#include "Abilities/GameplayAbilityTargetTypes.h"// 包含游戏技能目标类型的声明
#include "GameplayAbility.generated.h" // 包含游戏技能生成的头文件
// 声明一些与游戏技能相关的类
class UAbilitySystemComponent;
class UAnimMontage;
class UGameplayAbility;
class UGameplayTask;
class UGameplayTasksComponent;
// 定义一个结构体,用于在激活技能时启用日志记录
struct FScopedCanActivateAbilityLogEnabler
{
FScopedCanActivateAbilityLogEnabler() { ++LogEnablerCounter; }// 构造函数,增加日志记录计数器
~FScopedCanActivateAbilityLogEnabler() { --LogEnablerCounter; }// 析构函数,减少日志记录计数器
static bool IsLoggingEnabled() { return LogEnablerCounter > 0; }// 静态方法,判断是否启用日志记录
private:
static int32 LogEnablerCounter; // 日志记录计数器
};
/**
* UGameplayAbility
*
* 游戏技能定义了可以被激活或触发的自定义游戏逻辑。
*
* 技能系统为游戏技能提供的主要功能包括:
* -可用性功能:
* -冷却时间
* -成本(法力、耐力等)
* -等等
*
* -复制支持
* -客户端/服务器之间的技能激活通信
* -客户端预测技能激活
*
* -实例化支持
* -技能可以是非实例化的(仅本地)
* -每个所有者实例化
* -每次执行实例化(默认)
*
* -基础的,可扩展的:
* -输入绑定
* -'给予' 技能(可以使用)给角色
*
*
* 有关非实例化技能的示例,请参阅GameplayAbility_Montage
* -播放蒙太奇并在播放蒙太奇时对其目标应用GameplayEffect。
* -完成后,移除GameplayEffect。
*
* 关于复制支持的注意事项:
* -非实例化技能具有有限的复制支持。
* -不能有状态(显然),因此没有复制属性
* -技能类上的复制不能实现。
*
* 要支持状态或事件复制,必须实例化技能。这可以通过InstancingPolicy属性完成。
*/
// 当游戏技能结束时的通知委托定义
DECLARE_MULTICAST_DELEGATE_OneParam(FOnGameplayAbilityEnded, UGameplayAbility*);
// 当游戏技能被取消时的通知委托定义
DECLARE_MULTICAST_DELEGATE(FOnGameplayAbilityCancelled);
// 用于在状态结束时通知技能状态任务的通知委托
DECLARE_MULTICAST_DELEGATE_OneParam(FOnGameplayAbilityStateEnded, FName);
// 用于延迟执行直到我们离开临界区的委托
DECLARE_DELEGATE(FPostLockDelegate);
// 定义一个结构体,用于定义技能如何由外部事件触发
USTRUCT()
struct FAbilityTriggerData
{
GENERATED_USTRUCT_BODY()// 自动生成USTRUCT所需的代码
FAbilityTriggerData()
: TriggerSource(EGameplayAbilityTriggerSource::GameplayEvent)// 构造函数,设置触发源为游戏事件
{}
/** 要响应的标签 */
UPROPERTY(EditAnywhere, Category=TriggerData, meta=(Categories="TriggerTagCategory"))
FGameplayTag TriggerTag;
/** 要响应的触发类型 */
UPROPERTY(EditAnywhere, Category=TriggerData)
TEnumAsByte<EGameplayAbilityTriggerSource::Type> TriggerSource;
};
// 定义一个类,用于定义可以由玩家或外部游戏逻辑激活的自定义游戏逻辑
UCLASS(Blueprintable)
class GAMEPLAYABILITIES_API UGameplayAbility : public UObject, public IGameplayTaskOwnerInterface// 继承自UObject和IGameplayTaskOwnerInterface接口
{
GENERATED_UCLASS_BODY()
// 友元类声明,这些类可以在反射系统中访问UGameplayAbility的私有成员
friend class UAbilitySystemComponent;
friend class UGameplayAbilitySet;
friend struct FScopedTargetListLock;
public:
// ----------------------------------------------------------------------------------------------------------------
//
// The important functions:这段注释解释了UGameplayAbility类中一些重要函数的用途和行为
//
// CanActivateAbility() - 一个常量函数,用来检查技能是否可以被激活。可以被UI等调用。
//
// TryActivateAbility() - 尝试激活技能。会调用CanActivateAbility()。输入事件可以直接调用这个函数。
// - 也处理每次执行时的实例化逻辑以及复制/预测调用。
//
// CallActivateAbility() - 受保护的非虚拟函数。做一些激活前的样板工作,然后调用ActivateAbility()。
//
// ActivateAbility() - 技能所做的操作。子类需要覆盖这个函数。
//
// CommitAbility() - 提交资源/冷却时间等。ActivateAbility()必须调用这个函数!
//
// CancelAbility() - 从外部源中断技能。
//
// EndAbility() - 结束技能。这应该是由技能自身调用以结束自己。
//
// ----------------------------------------------------------------------------------------------------------------
// --------------------------------------
// Accessors 访问器
// --------------------------------------
/** 返回技能在执行时是如何实例化的。这限制了技能在其实现中可以执行的操作。 */
EGameplayAbilityInstancingPolicy::Type GetInstancingPolicy() const
{
return InstancingPolicy;
}
/** 返回技能如何在网络中复制状态/事件给每个人 */
EGameplayAbilityReplicationPolicy::Type GetReplicationPolicy() const
{
return ReplicationPolicy;
}
/** 技能在网络中在哪里执行?客户端是“询问并预测”、“询问并等待”还是“不问(直接执行)” */
EGameplayAbilityNetExecutionPolicy::Type GetNetExecutionPolicy() const
{
return NetExecutionPolicy;
}
/** 技能应该在网络中哪里执行?提供保护,防止客户端尝试执行受限的技能。 */
EGameplayAbilityNetSecurityPolicy::Type GetNetSecurityPolicy() const
{
return NetSecurityPolicy;
}
/** 返回与此技能关联的演员信息,缓存了指向有用对象的指针 */
UFUNCTION(BlueprintCallable, Category=Ability)
FGameplayAbilityActorInfo GetActorInfo() const;
/** 返回拥有此技能的演员,该演员可能没有物理位置 */
UFUNCTION(BlueprintCallable, Category = Ability)
AActor* GetOwningActorFromActorInfo() const;
/** 返回正在执行此技能的物理演员。可能为null */
UFUNCTION(BlueprintCallable, Category = Ability)
AActor* GetAvatarActorFromActorInfo() const;
/** 对于技能来说,获取骨骼网格组件的便捷方法 - 对于动画技能非常有用 */
UFUNCTION(BlueprintCallable, DisplayName = "GetSkeletalMeshComponentFromActorInfo", Category = Ability)
USkeletalMeshComponent* GetOwningComponentFromActorInfo() const;
/** 返回正在激活此技能的 AbilitySystemComponent */
UFUNCTION(BlueprintCallable, Category = Ability)
UAbilitySystemComponent* GetAbilitySystemComponentFromActorInfo() const;
// 以下是对GetAbilitySystemComponentFromActorInfo的重载,提供了额外的检查和确保机制
UAbilitySystemComponent* GetAbilitySystemComponentFromActorInfo_Checked() const;
UAbilitySystemComponent* GetAbilitySystemComponentFromActorInfo_Ensured() const;
/** 获取当前绑定到此技能的演员信息 - 只能在技能实例中调用 */
const FGameplayAbilityActorInfo* GetCurrentActorInfo() const;
/** 获取当前绑定到此技能的激活信息 - 只能在技能实例中调用 */
FGameplayAbilityActivationInfo GetCurrentActivationInfo() const;
/** 获取当前绑定到此技能的激活信息的引用 - 只能在技能实例中调用 */
FGameplayAbilityActivationInfo& GetCurrentActivationInfoRef()
{
// 检查是否为实例化的技能,如果不是,则抛出错误
checkf(IsInstantiated(), TEXT("%s: GetCurrentActivationInfoRef cannot be called on a non-instanced ability. Check the instancing policy."), *GetPathName());
return CurrentActivationInfo;
}
/** 获取当前的AbilitySpecHandle - 只能在技能实例中调用 */
FGameplayAbilitySpecHandle GetCurrentAbilitySpecHandle() const;
/** 检索此技能的实际操作AbilitySpec。只能在技能实例中调用。 */
FGameplayAbilitySpec* GetCurrentAbilitySpec() const;
/** 检索授予此技能的GameplayEffect的EffectContext。只能在技能实例中调用。 */
UFUNCTION(BlueprintCallable, Category = Ability)
FGameplayEffectContextHandle GetGrantedByEffectContext() const;
/**从我们的所有者和可选的TargetData生成GameplayEffectContextHandle。*/
UFUNCTION(BlueprintCallable, Category = Ability)
virtual FGameplayEffectContextHandle GetContextFromOwner(FGameplayAbilityTargetDataHandle OptionalTargetData) const;
/** 根据指定的演员信息返回一个效果上下文 */
virtual FGameplayEffectContextHandle MakeEffectContext(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo *ActorInfo) const;
/** 便捷方法,用于技能获取传出的游戏效果规格(例如,传递给投射物,以便应用于它们击中的任何人) */
UFUNCTION(BlueprintCallable, Category=Ability)
FGameplayEffectSpecHandle MakeOutgoingGameplayEffectSpec(TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level=1.f) const;
/** 上述函数的本地版本 */
virtual FGameplayEffectSpecHandle MakeOutgoingGameplayEffectSpec(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, TSubclassOf<UGameplayEffect> GameplayEffectClass, float Level = 1.f) const;
/** 将技能的标签添加到给定的GameplayEffectSpec中。这可能会根据项目被重写。 */
virtual void ApplyAbilityTagsToGameplayEffectSpec(FGameplayEffectSpec& Spec, FGameplayAbilitySpec* AbilitySpec) const;
/** 返回技能当前是否处于激活状态 */
bool IsActive() const;
/** 此技能是否由TriggerData触发(或者是通过输入/游戏代码显式触发的) */
bool IsTriggered() const;
/** 此技能是否在预测客户端上运行,单人游戏中这是假的 */
bool IsPredictingClient() const;
/** 如果这是在服务器上并且正在为非本地玩家执行,则为真,单人游戏中这是假的 */
bool IsForRemoteClient() const;
/** 如果拥有者演员是本地控制的,则为真,在单人游戏中为真 */
UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = Ability, Meta = (ExpandBoolAsExecs = "ReturnValue"))
bool IsLocallyControlled() const;
/** 如果这是服务器或者单人游戏,则为真 */
bool HasAuthority(const FGameplayAbilityActivationInfo* ActivationInfo) const;
//HasAuthority的蓝图版本
UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = Ability, DisplayName = "HasAuthority", Meta = (ExpandBoolAsExecs = "ReturnValue"))
bool K2_HasAuthority() const;
/** 如果我们能有效的预测键并且预期会工作,则为真 */
bool HasAuthorityOrPredictionKey(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo* ActivationInfo) const;
/** 如果已经被实例化,则为真,对于蓝图总是为真 */
bool IsInstantiated() const;
/** 技能结束时的通知。通过TryActivateAbility设置。 */
FOnGameplayAbilityEnded OnGameplayAbilityEnded;
/** 技能以某种方式结束时的通知 */
FGameplayAbilityEndedDelegate OnGameplayAbilityEndedWithData;
/** 技能被取消时的通知。在OnGameplayAbilityEnded之前调用。 */
FOnGameplayAbilityCancelled OnGameplayAbilityCancelled;
/** 技能状态任务用来处理状态结束时的事件 */
FOnGameplayAbilityStateEnded OnGameplayAbilityStateEnded;
/** 当这个技能被服务器确认时的回调 */
FGenericAbilityDelegate OnConfirmDelegate;
// --------------------------------------
// CanActivateAbility 能否激活技能
// --------------------------------------
/** 返回如果当前可以激活此技能,则为真。没有副作用 */
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;
/** 返回如果此技能现在可以被触发,则为真。没有副作用 */
virtual bool ShouldAbilityRespondToEvent(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayEventData* Payload) const;
/** 返回是否应该激活此技能 */
virtual bool ShouldActivateAbility(ENetRole Role) const;
/** 返回当前激活的冷却时间剩余的秒数。 */
UFUNCTION(BlueprintCallable, Category = Ability)
float GetCooldownTimeRemaining() const;
/** 返回当前激活的冷却时间剩余的秒数。 */
virtual float GetCooldownTimeRemaining(const FGameplayAbilityActorInfo* ActorInfo) const;
/** 返回当前激活的冷却时间剩余的秒数和此冷却的原始持续时间。 */
virtual void GetCooldownTimeRemainingAndDuration(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, float& TimeRemaining, float& CooldownDuration) const;
/** 返回所有可以将此技能置入冷却的标签 */
virtual const FGameplayTagContainer* GetCooldownTags() const;
/** 如果技能的标签没有被封锁,并且没有“阻塞”标签,并且具有所有“必需”标签,则返回真。 */
virtual bool DoesAbilitySatisfyTagRequirements(const UAbilitySystemComponent& AbilitySystemComponent, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;
/** 如果此技能正在阻止其他技能,则返回真 */
virtual bool IsBlockingOtherAbilities() const;
/** 设置技能阻塞标志是否启用或禁用。仅对实例化的技能有效 */
UFUNCTION(BlueprintCallable, Category = Ability)
virtual void SetShouldBlockOtherAbilities(bool bShouldBlockAbilities);
// --------------------------------------
// CancelAbility 取消技能
// --------------------------------------
/** 销毁每次执行时实例化的技能。每个执行对应一个实例的技能应该“重置”。任何活跃的技能状态任务都会接收到'OnAbilityStateInterrupted'事件。非实例化的技能 - 我们能做什么? */
virtual void CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancelAbility);
/** 从蓝图调用以自然取消技能 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "CancelAbility", meta=(ScriptName = "CancelAbility"))
void K2_CancelAbility();
/** 返回此技能是否可以被取消 */
virtual bool CanBeCanceled() const;
/** 设置技能是否应该忽略取消请求。仅对实例化的技能有效 */
UFUNCTION(BlueprintCallable, Category=Ability)
virtual void SetCanBeCanceled(bool bCanBeCanceled);
// --------------------------------------
// CommitAbility 提交技能 的消耗和冷却
// --------------------------------------
/** 尝试提交技能(消耗资源等)。这是我们最后的机会来失败。覆盖ActivateAbility的子类必须自己调用这个函数! */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "CommitAbility", meta=(ScriptName = "CommitAbility"))
virtual bool K2_CommitAbility();
/** 仅尝试提交技能的冷却时间。如果BroadcastCommitEvent为true,它将广播提交事件,像WaitAbilityCommit这样的任务会监听这个事件。 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "CommitAbilityCooldown", meta=(ScriptName = "CommitAbilityCooldown"))
virtual bool K2_CommitAbilityCooldown(bool BroadcastCommitEvent=false, bool ForceCooldown=false);
/** 仅尝试提交技能的成本。如果BroadcastCommitEvent为true,它将广播提交事件,像WaitAbilityCommit这样的任务会监听这个事件。 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "CommitAbilityCost", meta=(ScriptName = "CommitAbilityCost"))
virtual bool K2_CommitAbilityCost(bool BroadcastCommitEvent=false);
/** 检查技能的冷却时间,但不应用它。*/
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "CheckAbilityCooldown", meta=(ScriptName = "CheckAbilityCooldown"))
virtual bool K2_CheckAbilityCooldown();
/** 检查技能的成本,但不应用它。 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "CheckAbilityCost", meta=(ScriptName = "CheckAbilityCost"))
virtual bool K2_CheckAbilityCost();
// 以下是一些虚拟函数,用于在提交技能时执行特定的检查和操作
virtual bool CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
virtual bool CommitAbilityCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const bool ForceCooldown, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
virtual bool CommitAbilityCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
/** 在提交之前的最后机会失败,这通常会与CanActivateAbility相同。如果它们在CommitExecute中消耗了额外的资源,一些技能可能需要在这里进行额外的检查 */
virtual bool CommitCheck(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr);
/** 从蓝图调用函数CommitAbility */
UFUNCTION(BlueprintImplementableEvent, Category = Ability, DisplayName = "CommitExecute", meta = (ScriptName = "CommitExecute"))
void K2_CommitExecute();
/** 原子性地执行提交(消耗资源、执行冷却时间等) */
virtual void CommitExecute(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo);
/** 返回用于确定冷却时间的游戏效果 */
virtual UGameplayEffect* GetCooldownGameplayEffect() const;
/** 返回用于应用成本的游戏效果 */
virtual UGameplayEffect* GetCostGameplayEffect() const;
/** 检查冷却时间。如果可以再次使用则返回真,否则返回假 */
virtual bool CheckCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;
/** 将CooldownGameplayEffect应用到目标 */
virtual void ApplyCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const;
/** 检查成本。如果可以支付技能则返回真,否则返回假 */
virtual bool CheckCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const;
/** 将技能的成本应用到目标 */
virtual void ApplyCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const;
// --------------------------------------
// Input 输入 InputPressed和InputReleased函数是虚函数,它们作为输入绑定的存根存在。在实际的游戏逻辑中,这些函数通常会被重写以响应玩家的输入事件
// --------------------------------------
/** 触发技能按下 */
virtual void InputPressed(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) {};
/** 触发技能抬起 */
virtual void InputReleased(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) {};
/** 从AbilityTask_WaitConfirmCancel调用,用于处理输入确认
* OnWaitingForConfirmInputBegin和OnWaitingForConfirmInputEnd函数用于处理等待确认输入的情况。这些函数可能在技能激活的确认/取消逻辑中被调用,例如在玩家需要按下按钮来确认或取消技能激活时。
*/
virtual void OnWaitingForConfirmInputBegin() {}
virtual void OnWaitingForConfirmInputEnd() {}
// --------------------------------------
// Animation 动画
// --------------------------------------
/** 用于获取当前与技能关联的蒙太奇动画(如果有的话) */
UFUNCTION(BlueprintCallable, Category = Animation)
UAnimMontage* GetCurrentMontage() const;
/** 设置当前的蒙太奇动画,这通常用于将蒙太奇事件与技能事件关联起来,例如在技能激活时播放特定的动画序列 */
virtual void SetCurrentMontage(class UAnimMontage* InCurrentMontage);
/** 设置移动同步点,但由于在Unreal Engine 5.3版本中没有实际用途,已被标记为弃用(deprecated),并计划在未来的引擎版本中移除。 */
UE_DEPRECATED(5.3, "This serves no purpose and will be removed in future engine versions")
virtual void SetMovementSyncPoint(FName SyncName);
// ----------------------------------------------------------------------------------------------------------------
// Ability Levels and source objects 技能等级和源对象
// ----------------------------------------------------------------------------------------------------------------
/** 获取当前技能的等级 */
UFUNCTION(BlueprintCallable, Category = Ability)
int32 GetAbilityLevel() const;
/** 返回非实例化技能的当前等级。你必须在这些上下文中调用这个版本! */
int32 GetAbilityLevel(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const;
/** GetAbilityLevel的蓝图版本 */
UFUNCTION(BlueprintCallable, Category = Ability, meta = (DisplayName = "GetAbilityLevelNonInstanced", ReturnDisplayName = "AbilityLevel"))
int32 GetAbilityLevel_BP(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo& ActorInfo) const;
/** 检索与此技能关联的SourceObject。只能在实例化的技能上调用。 */
UFUNCTION(BlueprintCallable, Category = Ability)
UObject* GetCurrentSourceObject() const;
/** 检索与此技能关联的SourceObject。可以在非实例化的技能上调用。 */
UObject* GetSourceObject(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const;
/** GetSourceObject的蓝图版本 */
UFUNCTION(BlueprintCallable, Category = Ability, meta = (DisplayName = "GetSourceObjectNonInstanced", ReturnDisplayName = "SourceObject"))
UObject* GetSourceObject_BP(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo& ActorInfo) const;
// --------------------------------------
// Interaction with ability system component 与ASC的交互
// --------------------------------------
/** ASC调用此函数以通知此技能实例远程实例已结束 */
virtual void SetRemoteInstanceHasEnded();
/** 通知技能AvatarActor已被替换。如果技能依赖于avatar状态,它可能需要结束自己 */
virtual void NotifyAvatarDestroyed();
/** 通知技能有任务正在等待玩家执行某些操作 */
virtual void NotifyAbilityTaskWaitingOnPlayerData(class UAbilityTask* AbilityTask);
/** 通知技能有任务正在等待玩家的avatar在世界中执行某些操作 */
virtual void NotifyAbilityTaskWaitingOnAvatar(class UAbilityTask* AbilityTask);
/** 当技能被赋予ASC时调用 */
virtual void OnGiveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec);
/** 当技能从ASC中移除时调用 */
virtual void OnRemoveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec) {}
/** 当avatar actor被设置/更改时调用 */
virtual void OnAvatarSet(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec);
/** 它接收技能规格(ability spec),并检查是否应该允许该技能规格上的复制。这不会阻止技能UObject本身的复制,而只是阻止位于UAbilitySystemComponent的ActivatableAbilities内部针对这个技能的规格复制。 */
virtual bool ShouldReplicateAbilitySpec(const FGameplayAbilitySpec& AbilitySpec) const
{
return true;
}
/**
* 使当前预测键无效。这应该用在有有效预测窗口的情况下,但服务器正在执行只有它能做的逻辑,之后执行客户端本来可以预测的动作(如果客户端能够先运行服务器独有的代码)。
* 这个函数会立即返回,除了清除当前预测键之外没有其他副作用。
*/
UFUNCTION(BlueprintCallable, Category = Ability)
void InvalidateClientPredictionKey() const;
/** 移除授予此技能的GameplayEffect。只能在实例化的技能上调用 */
UFUNCTION(BlueprintCallable, Category = Ability)
virtual void RemoveGrantedByEffect();
/** 向用户添加一个调试消息 */
void AddAbilityTaskDebugMessage(UGameplayTask* AbilityTask, FString DebugMessage);
// --------------------------------------
// 公共变量,为了向后兼容性而暴露
// --------------------------------------
/** 这个技能有这些标签 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="AbilityTagCategory"))
FGameplayTagContainer AbilityTags;
/** 如果为真,这个技能将总是将输入按下/释放事件复制到服务器。 */
UPROPERTY(EditDefaultsOnly, Category = Input)
bool bReplicateInputDirectly;
/** 当这个技能的远程实例结束时设置(但本地实例可能仍在运行或完成中) */
UPROPERTY()
bool RemoteInstanceEnded;
// --------------------------------------
// 覆写 UObject 成员函数
// --------------------------------------
virtual UWorld* GetWorld() const override;
virtual int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;
virtual bool CallRemoteFunction(UFunction* Function, void* Parameters, FOutParmRec* OutParms, FFrame* Stack) override;
virtual bool IsSupportedForNetworking() const override;
#if UE_WITH_IRIS
/** Register all replication fragments */
virtual void RegisterReplicationFragments(UE::Net::FFragmentRegistrationContext& Context, UE::Net::EFragmentRegistrationFlags RegistrationFlags) override;
#endif // UE_WITH_IRIS
// --------------------------------------
// IGameplayTaskOwnerInterface
// --------------------------------------
virtual UGameplayTasksComponent* GetGameplayTasksComponent(const UGameplayTask& Task) const override;
virtual AActor* GetGameplayTaskOwner(const UGameplayTask* Task) const override;
virtual AActor* GetGameplayTaskAvatar(const UGameplayTask* Task) const override;
virtual void OnGameplayTaskInitialized(UGameplayTask& Task) override;
virtual void OnGameplayTaskActivated(UGameplayTask& Task) override;
virtual void OnGameplayTaskDeactivated(UGameplayTask& Task) override;
protected:
// --------------------------------------
// ShouldAbilityRespondToEvent
// --------------------------------------
/** 如果这个技能现在可以被激活,则返回true。没有副作用,蓝图可调用 */
UFUNCTION(BlueprintImplementableEvent, Category = Ability, DisplayName = "ShouldAbilityRespondToEvent", meta=(ScriptName = "ShouldAbilityRespondToEvent"))
bool K2_ShouldAbilityRespondToEvent(FGameplayAbilityActorInfo ActorInfo, FGameplayEventData Payload) const;
/** 一个标志,表示是否在蓝图(Blueprint)中实现了 ShouldAbilityRespondToEvent 事件 */
bool bHasBlueprintShouldAbilityRespondToEvent;
/** 发送一个游戏事件,并创建一个预测窗口 */
UFUNCTION(BlueprintCallable, Category = Ability)
virtual void SendGameplayEvent(FGameplayTag EventTag, FGameplayEventData Payload);
// --------------------------------------
// CanActivate
// --------------------------------------
/** 如果当前可以激活这个技能,则返回true。这个函数没有副作用。 */
UFUNCTION(BlueprintImplementableEvent, Category = Ability, DisplayName="CanActivateAbility", meta=(ScriptName="CanActivateAbility"))
bool K2_CanActivateAbility(FGameplayAbilityActorInfo ActorInfo, const FGameplayAbilitySpecHandle Handle, FGameplayTagContainer& RelevantTags) const;
//其用途可能是在类的其他部分或蓝图中追踪是否有一个蓝图实现了CanActivateAbility事件。这样,你可以根据这个标志来决定是否调用蓝图中的实现或默认的C++实现。
bool bHasBlueprintCanUse;
// --------------------------------------
// ActivateAbility 激活技能
// --------------------------------------
/**
* 定义技能主要功能的功能。
* -子类可以覆盖此类的实现
* -函数实现需要调用CommitAbility
* -函数实现需要调用EndAbility
*
* 在这个图中允许使用延迟/异步动作。注意,Commit和EndAbility调用要求适用于K2_ActivateAbility图。
* 在C++中,调用K2_ActivateAbility()可能会在没有调用CommitAbility或EndAbility的情况下返回。
* 但是预计这只会在有延迟/异步动作待处理时发生。当K2_ActivateAbility逻辑上完成时,我们预期Commit/End已经被调用。
*
*/
UFUNCTION(BlueprintImplementableEvent, Category = Ability, DisplayName = "ActivateAbility", meta=(ScriptName = "ActivateAbility"))
void K2_ActivateAbility();
UFUNCTION(BlueprintImplementableEvent, Category = Ability, DisplayName = "ActivateAbilityFromEvent", meta=(ScriptName = "ActivateAbilityFromEvent"))
void K2_ActivateAbilityFromEvent(const FGameplayEventData& EventData);
bool bHasBlueprintActivate;
bool bHasBlueprintActivateFromEvent;
/** 实际激活技能,不要直接调用这个函数 */
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData);
/** 执行初始化工作,然后调用ActivateAbility */
virtual void PreActivate(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData = nullptr);
/** 执行PreActivate和ActivateAbility */
void CallActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate = nullptr, const FGameplayEventData* TriggerEventData = nullptr);
/** 当服务器确认其执行时,对预测技能调用 */
virtual void ConfirmActivateSucceed();
// -------------------------------------
// EndAbility 结束技能
// -------------------------------------
/** 从蓝图调用以强制结束技能,而不取消它。这将会复制结束技能到客户端或服务器,可以中断任务 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName="End Ability", meta=(ScriptName = "EndAbility"))
virtual void K2_EndAbility();
/** 从蓝图调用以自然结束技能。这只会在本地结束预测的技能,允许它在客户端或服务器上自然结束 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "End Ability Locally", meta = (ScriptName = "EndAbilityLocally"))
virtual void K2_EndAbilityLocally();
/** 蓝图事件,如果技能正常或异常结束将被调用 */
UFUNCTION(BlueprintImplementableEvent, Category = Ability, DisplayName = "OnEndAbility", meta=(ScriptName = "OnEndAbility"))
void K2_OnEndAbility(bool bWasCancelled);
/** 检查技能是否可以结束 */
bool IsEndAbilityValid(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const;
/** 原生函数,如果技能正常或异常结束将被调用。如果bReplicate设置为true,尝试将结束复制到客户端/服务器 */
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled);
// -------------------------------------
// Apply Gameplay effects to Self 应用游戏效果到自身
// -------------------------------------
/** 将一个游戏效果应用到这个技能的拥有者上 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName="ApplyGameplayEffectToOwner", meta=(ScriptName="ApplyGameplayEffectToOwner"))
FActiveGameplayEffectHandle BP_ApplyGameplayEffectToOwner(TSubclassOf<UGameplayEffect> GameplayEffectClass, int32 GameplayEffectLevel = 1, int32 Stacks = 1);
/** 不能从蓝图调用,可以安全地在CDO/非实例化技能上调用 */
FActiveGameplayEffectHandle ApplyGameplayEffectToOwner(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const UGameplayEffect* GameplayEffect, float GameplayEffectLevel, int32 Stacks = 1) const;
/** 将之前创建的游戏效果规格应用到这个技能的拥有者上 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "ApplyGameplayEffectSpecToOwner", meta=(ScriptName = "ApplyGameplayEffectSpecToOwner"))
FActiveGameplayEffectHandle K2_ApplyGameplayEffectSpecToOwner(const FGameplayEffectSpecHandle EffectSpecHandle);
FActiveGameplayEffectHandle ApplyGameplayEffectSpecToOwner(const FGameplayAbilitySpecHandle AbilityHandle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEffectSpecHandle SpecHandle) const;
// -------------------------------------
// Apply Gameplay effects to Target 应用GE到目标
// -------------------------------------
/** 将一个游戏效果应用到目标 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "ApplyGameplayEffectToTarget", meta=(ScriptName = "ApplyGameplayEffectToTarget"))
TArray<FActiveGameplayEffectHandle> BP_ApplyGameplayEffectToTarget(FGameplayAbilityTargetDataHandle TargetData, TSubclassOf<UGameplayEffect> GameplayEffectClass, int32 GameplayEffectLevel = 1, int32 Stacks = 1);
/** 不能从蓝图调用,可以安全地在CDO/非实例化技能上调用 */
TArray<FActiveGameplayEffectHandle> ApplyGameplayEffectToTarget(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayAbilityTargetDataHandle& Target, TSubclassOf<UGameplayEffect> GameplayEffectClass, float GameplayEffectLevel, int32 Stacks = 1) const;
/** 将之前创建的游戏效果规格应用到目标 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "ApplyGameplayEffectSpecToTarget", meta=(ScriptName = "ApplyGameplayEffectSpecToTarget"))
TArray<FActiveGameplayEffectHandle> K2_ApplyGameplayEffectSpecToTarget(const FGameplayEffectSpecHandle EffectSpecHandle, FGameplayAbilityTargetDataHandle TargetData);
TArray<FActiveGameplayEffectHandle> ApplyGameplayEffectSpecToTarget(const FGameplayAbilitySpecHandle AbilityHandle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEffectSpecHandle SpecHandle, const FGameplayAbilityTargetDataHandle& TargetData) const;
// -------------------------------------
// Remove Gameplay effects from Self 从自身移除效果
// -------------------------------------
/** 移除拥有者上与给定资产等级标签匹配的游戏效果 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName="RemoveGameplayEffectFromOwnerWithAssetTags", meta=(ScriptName="RemoveGameplayEffectFromOwnerWithAssetTags"))
void BP_RemoveGameplayEffectFromOwnerWithAssetTags(FGameplayTagContainer WithAssetTags, int32 StacksToRemove = -1);
/** 用于移除拥有者上授予的、与特定标签容器匹配的游戏效果 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName="RemoveGameplayEffectFromOwnerWithGrantedTags", meta=(ScriptName="RemoveGameplayEffectFromOwnerWithGrantedTags"))
void BP_RemoveGameplayEffectFromOwnerWithGrantedTags(FGameplayTagContainer WithGrantedTags, int32 StacksToRemove = -1);
/** 允许从蓝图中调用,用于移除与特定FActiveGameplayEffectHandle句柄匹配的游戏效果。 */
UFUNCTION(BlueprintCallable, Category = Ability, DisplayName = "RemoveGameplayEffectFromOwnerWithHandle", meta=(ScriptName = "RemoveGameplayEffectFromOwnerWithHandle"))
void BP_RemoveGameplayEffectFromOwnerWithHandle(FActiveGameplayEffectHandle Handle, int32 StacksToRemove = -1);
// -------------------------------------
// GameplayCue 游戏提示效果
// 技能可以在不创建GE的情况下调用GC
// -------------------------------------
/** 在技能拥有者上触发一个游戏提示 */
UFUNCTION(BlueprintCallable, Category = Ability, meta=(GameplayTagFilter="GameplayCue"), DisplayName="Execute GameplayCue On Owner", meta=(ScriptName="ExecuteGameplayCue"))
virtual void K2_ExecuteGameplayCue(FGameplayTag GameplayCueTag, FGameplayEffectContextHandle Context);
/** 在技能拥有者上触发一个带有额外参数的游戏提示 */
UFUNCTION(BlueprintCallable, Category = Ability, meta = (GameplayTagFilter = "GameplayCue"), DisplayName = "Execute GameplayCueWithParams On Owner", meta=(ScriptName = "ExecuteGameplayCueWithParams"))
virtual void K2_ExecuteGameplayCueWithParams(FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters);
/** 向技能拥有者添加一个持久的游戏提示。可选地,如果技能结束,则移除 */
UFUNCTION(BlueprintCallable, Category = Ability, meta=(GameplayTagFilter="GameplayCue"), DisplayName="Add GameplayCue To Owner", meta=(ScriptName="AddGameplayCue"))
virtual void K2_AddGameplayCue(FGameplayTag GameplayCueTag, FGameplayEffectContextHandle Context, bool bRemoveOnAbilityEnd = true);
/** 向技能拥有者添加一个持久的游戏提示。可选地,如果技能结束,则移除 */
UFUNCTION(BlueprintCallable, Category = Ability, meta = (GameplayTagFilter = "GameplayCue"), DisplayName = "Add GameplayCueWithParams To Owner", meta=(ScriptName = "AddGameplayCueWithParams"))
virtual void K2_AddGameplayCueWithParams(FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameter, bool bRemoveOnAbilityEnd = true);
/** 从技能拥有者移除一个持久的游戏提示 */
UFUNCTION(BlueprintCallable, Category = Ability, meta=(GameplayTagFilter="GameplayCue"), DisplayName="Remove GameplayCue From Owner", meta=(ScriptName="RemoveGameplayCue"))
virtual void K2_RemoveGameplayCue(FGameplayTag GameplayCueTag);
// -------------------------------------
// Protected properties 受保护的属性,这些属性用于控制技能在网络上的复制、实例化策略以及消耗和冷却类的设置。这些数值可以在蓝图中设置。
// -------------------------------------
/** 技能如何在网络上复制状态/事件给每个人。对于NetExecutionPolicy不需要复制。 */
UPROPERTY(EditDefaultsOnly, Category = Advanced)
TEnumAsByte<EGameplayAbilityReplicationPolicy::Type> ReplicationPolicy;
/** 技能在执行时是如何实例化的。这限制了技能在其实现中可以执行的操作。 */
UPROPERTY(EditDefaultsOnly, Category = Advanced)
TEnumAsByte<EGameplayAbilityInstancingPolicy::Type> InstancingPolicy;
/** 如果设置了,技能服务器端版本可以被客户端版本取消。客户端版本总是可以被服务器取消。 */
UPROPERTY(EditDefaultsOnly, Category = Advanced)
bool bServerRespectsRemoteAbilityCancellation;
/** 如果为true,并且尝试激活一个已经激活的实例化技能,结束它并重新触发它。 */
UPROPERTY(EditDefaultsOnly, Category = Advanced)
bool bRetriggerInstancedAbility;
/** 这是特定于技能实例的信息。例如,它是否在预测、授权、确认等。 */
UPROPERTY(BlueprintReadOnly, Category = Ability)
FGameplayAbilityActivationInfo CurrentActivationInfo;
/** 如果是通过事件激活的技能,这是特定于此技能实例的信息 */
UPROPERTY(BlueprintReadOnly, Category = Ability)
FGameplayEventData CurrentEventData;
/** 技能在网络上是如何执行的。客户端是“询问并预测”、“询问并等待”还是“不问(直接执行)”。 */
UPROPERTY(EditDefaultsOnly, Category=Advanced)
TEnumAsByte<EGameplayAbilityNetExecutionPolicy::Type> NetExecutionPolicy;
/** 这个技能有哪些保护措施?客户端是否被允许请求更改技能的执行? */
UPROPERTY(EditDefaultsOnly, Category = Advanced)
TEnumAsByte<EGameplayAbilityNetSecurityPolicy::Type> NetSecurityPolicy;
/** 这个GameplayEffect代表了技能的成本(法力、耐力等)。当技能被提交时,它将被应用。 */
UPROPERTY(EditDefaultsOnly, Category = Costs)
TSubclassOf<class UGameplayEffect> CostGameplayEffectClass;
/** 触发器,用于确定这个技能是否应该响应事件执行 */
UPROPERTY(EditDefaultsOnly, Category = Triggers)
TArray<FAbilityTriggerData> AbilityTriggers;
/** 这个GameplayEffect代表了冷却时间。当技能被提交时,它将被应用,并且技能在过期前不能再次使用。 */
UPROPERTY(EditDefaultsOnly, Category = Cooldowns)
TSubclassOf<class UGameplayEffect> CooldownGameplayEffectClass;
// ----------------------------------------------------------------------------------------------------------------
// Ability exclusion / canceling 技能 排除/取消 当前参数可以在蓝图中设置
// ----------------------------------------------------------------------------------------------------------------
/** 当这个技能被执行时,带有这些标签的技能将被取消。 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="AbilityTagCategory"))
FGameplayTagContainer CancelAbilitiesWithTag;
/** 当这个技能处于激活状态时,带有这些标签的技能将被阻止 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="AbilityTagCategory"))
FGameplayTagContainer BlockAbilitiesWithTag;
/** 当这个技能激活时,要应用到激活所有者上的标签。如果AbilitySystemGlobals中启用了ReplicateActivationOwnedTags,则这些标签会被复制 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="OwnedTagsCategory"))
FGameplayTagContainer ActivationOwnedTags;
/** 只有当激活的演员/组件具有所有这些标签时,这个技能才能被激活 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="OwnedTagsCategory"))
FGameplayTagContainer ActivationRequiredTags;
/** 如果激活的演员/组件具有这些标签中的任何一个,这个技能将被阻止 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="OwnedTagsCategory"))
FGameplayTagContainer ActivationBlockedTags;
/** 只有当源演员/组件具有所有这些标签时,这个技能才能被激活 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="SourceTagsCategory"))
FGameplayTagContainer SourceRequiredTags;
/** 如果源演员/组件具有这些标签中的任何一个,这个技能将被阻止 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="SourceTagsCategory"))
FGameplayTagContainer SourceBlockedTags;
/** 只有当目标演员/组件具有所有这些标签时,这个技能才能被激活 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="TargetTagsCategory"))
FGameplayTagContainer TargetRequiredTags;
/** 如果目标演员/组件具有这些标签中的任何一个,这个技能将被阻止 */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="TargetTagsCategory"))
FGameplayTagContainer TargetBlockedTags;
// ----------------------------------------------------------------------------------------------------------------
// Ability Tasks 技能任务
// ----------------------------------------------------------------------------------------------------------------
/** 查找所有当前激活的、名为InstanceName的任务,并确认它们。具体含义取决于个别任务。如果bEndTask为true,默认情况下除了结束之外不做其他操作。 */
UFUNCTION(BlueprintCallable, Category = Ability)
void ConfirmTaskByInstanceName(FName InstanceName, bool bEndTask);
/** 内部函数,取消上一次我们要求取消的所有任务(按实例名称)。 */
void EndOrCancelTasksByInstanceName();
TArray<FName> CancelTaskInstanceNames;
/** 将任何具有此实例名称的任务添加到下一个帧将被结束(而不是取消)的列表中。另见CancelTaskByInstanceName。 */
UFUNCTION(BlueprintCallable, Category = Ability)
void EndTaskByInstanceName(FName InstanceName);
TArray<FName> EndTaskInstanceNames;
/** 将任何具有此实例名称的任务添加到下一个帧将被取消(而不是结束)的列表中。另见EndTaskByInstanceName。 */
UFUNCTION(BlueprintCallable, Category = Ability)
void CancelTaskByInstanceName(FName InstanceName);
/** 结束任何具有给定名称的活跃技能状态任务。如果名称为'None',则结束所有活跃状态(以任意顺序)。 */
UFUNCTION(BlueprintCallable, Category = Ability)
void EndAbilityState(FName OptionalStateNameToEnd);
/** 当前活跃任务的列表,不要直接修改 */
UPROPERTY()
TArray<TObjectPtr<UGameplayTask>> ActiveTasks;
/** 任务可以在它们的生命周期中发出调试消息以供调试目的。保存在技能上,以便在任务完成后仍然存在 */
TArray<FAbilityTaskDebugMessage> TaskDebugMessages;
// ----------------------------------------------------------------------------------------------------------------
// Animation 动画
// ----------------------------------------------------------------------------------------------------------------
/** 立即将活动蒙太奇跳转到指定的部分 */
UFUNCTION(BlueprintCallable, Category="Ability|Animation")
void MontageJumpToSection(FName SectionName);
/** 设置活动蒙太奇的下一个部分名称 */
UFUNCTION(BlueprintCallable, Category = "Ability|Animation")
void MontageSetNextSectionName(FName FromSectionName, FName ToSectionName);
/**
* 停止当前的动画蒙太奇。
*
* @param OverrideBlendTime 如果大于或等于0,将覆盖AnimMontage实例上的BlendOutTime参数
*/
UFUNCTION(BlueprintCallable, Category="Ability|Animation", Meta = (AdvancedDisplay = "OverrideBlendOutTime"))
void MontageStop(float OverrideBlendOutTime = -1.0f);
/** 此技能正在播放的活动蒙太奇 */
UPROPERTY()
TObjectPtr<class UAnimMontage> CurrentMontage;
// ----------------------------------------------------------------------------------------------------------------
// Target Data 目标数据
// ----------------------------------------------------------------------------------------------------------------
/** 从拥有者avatar的位置创建一个目标位置 */
UFUNCTION(BlueprintPure, Category = Ability)
FGameplayAbilityTargetingLocationInfo MakeTargetLocationInfoFromOwnerActor();
/** 从拥有者avatar的骨骼网格组件上的插座创建一个目标位置 */
UFUNCTION(BlueprintPure, Category = Ability)
FGameplayAbilityTargetingLocationInfo MakeTargetLocationInfoFromOwnerSkeletalMeshComponent(FName SocketName);
// ----------------------------------------------------------------------------------------------------------------
// Setters for temporary execution data 临时执行数据的设置函数
// ----------------------------------------------------------------------------------------------------------------
/** 在由于复制而被创建后,被调用以进行初始化 */
virtual void PostNetInit();
/** 修改actor信息,仅在实例化的技能上是安全的 */
virtual void SetCurrentActorInfo(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const;
/** 修改激活信息,仅在实例化的技能上是安全的 */
virtual void SetCurrentActivationInfo(const FGameplayAbilityActivationInfo ActivationInfo);
/** 设置actor和激活信息 */
void SetCurrentInfo(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo);
/**
* 这是关于使用我们的实体的共享、缓存信息
* E.g, Actor*, MovementComponent*, AnimInstance, etc.
* 希望每个actor分配一次并由多个技能共享。
* 实际的结构可能根据游戏需要被覆盖以包含特定于游戏的数据。
* (例如,子类可能希望将其转换为FMyGameAbilityActorInfo)
CurrentActorInfo是一个可变的指针,指向当前使用技能的实体的信息,例如角色、移动组件或动画实例。这个信息被缓存并共享,以减少重复的内存分配。
*/
mutable const FGameplayAbilityActorInfo* CurrentActorInfo;
/** 用于实例化的技能的规格句柄 */
mutable FGameplayAbilitySpecHandle CurrentSpecHandle;
/** 在这个技能期间添加的游戏提示,当技能结束时将自动移除 */
TSet<FGameplayTag> TrackedGameplayCues;
/** 如果技能当前处于激活状态,则为真。对于每个所有者实例化的技能 */
UPROPERTY()
bool bIsActive;
/** 如果结束技能已被调用,但尚未完成,则为真。 */
UPROPERTY()
bool bIsAbilityEnding = false;
/** 如果技能当前可以被取消,则为真,否则只会通过EndAbility调用被取消。 */
UPROPERTY()
bool bIsCancelable;
/** 否当前正在阻止其他技能的激活 */
UPROPERTY()
bool bIsBlockingOtherAbilities;
/** 所有当前作用域锁的计数。用于管理技能的作用域锁定,防止在技能执行期间并行执行其他操作。 */
mutable int8 ScopeLockCount;
/** 等待作用域锁结束以便运行的所有函数的列表。包含所有等待作用域锁结束以便执行的委托函数 */
mutable TArray<FPostLockDelegate> WaitingToExecute;
/** 增加作用域锁计数。 */
void IncrementListLock() const;
/** 减少作用域锁计数。如果计数降至零,则运行等待执行的委托。 */
void DecrementListLock() const;
public:
/** 当这个标志被设置时,它表示在技能结束时,应该将该技能标记为待删除。 */
void SetMarkPendingKillOnAbilityEnd(bool bInMarkPendingKillOnAbilityEnd) { bMarkPendingKillOnAbilityEnd = bInMarkPendingKillOnAbilityEnd; }
/** 用于查询bMarkPendingKillOnAbilityEnd标志是否已经被设置。如果返回true,则表示该技能在结束时将被标记为待删除。 */
bool IsMarkPendingKillOnAbilityEnd() const { return bMarkPendingKillOnAbilityEnd; }
protected:
/**由AbilitySystemComponent::OnRemoveAbility方法设置。当这个方法被调用时,它将这个标志设置为true,以指示在AbilitySystemComponent::NotifyAbilityEnded事件被触发时,该技能需要被清理。 */
UPROPERTY(BlueprintReadOnly, Category = Ability)
bool bMarkPendingKillOnAbilityEnd;
};
在源码中,我可以看到技能的简介,以及内置的一些函数属性,并且可以看到在技能蓝图中设置的属性在代码里面是如何设置的。
里面带有注释,介绍了技能的功能:
- 支持使用技能冷却时间,以及资源消耗(法力,体力等)
- 支持客户端和服务端的复制,预测功能
- 实例化,支持非实例化(本地)每个所有者实例化,每次执行都实例化(默认)
- 输入绑定技能激活,应用技能。
- 支持Task,通过Task可以在技能内部实现异步处理。
我们实现的技能相当于是一个类,它可以直接被使用,或者实例化以后使用它的实例。
里面有一些常用的函数:
- CanActivateAbility() - 判断技能是否可以被激活
- TryActivateAbility() - 尝试激活技能
- CallActivateAbility() - 做一些激活前的工作,然后调用ActivateAbility()
- ActivateAbility() - 激活技能事件回调,在技能激活后,可以实现自定义逻辑,推荐在子类中覆盖。
- CommitAbility() - 提交资源/冷却时间等。ActivateAbility()必须调用这个函数!
- CancelAbility() - 从外部取消函数
- EndAbility() - 这个函数是自身调用技能结束。