1 资产标签(默认能力标签)AssetTags (Default AbilityTags)
定义:
UPROPERTY(EditDefaultsOnly,
Category = Tags,
DisplayName="AssetTags (Default AbilityTags)",
meta=(Categories="AbilityTagCategory"))
FGameplayTagContainer AbilityTags;
追溯只找到了Get和Set:
const FGameplayTagContainer& UGameplayAbility::GetAssetTags() const
{
return AbilityTags;
}
void UGameplayAbility::SetAssetTags(const FGameplayTagContainer& InAssetTags)
{
ensureMsgf(HasAnyFlags(RF_NeedInitialization), TEXT("%hs should only be used during construction as GetAbilityTags() are primarily read from the CDO"), __func__);
AbilityTags = InAssetTags;
}
之后通过Get找到了这些:
//DoesAbilitySatisfyTagRequirements中的
CheckForBlocked(AbilitySystemComponent.GetBlockedAbilityTags(), GetAssetTags());
我的理解是和ASC中阻塞的能力标签比较,要是资产标签中带有ASC中要阻塞的能力的标签,就会阻塞,不通过标签检查。
void UGameplayAbility::SetCanBeCanceled(bool bCanBeCanceled)
{
if (GetInstancingPolicy() != EGameplayAbilityInstancingPolicy::NonInstanced && bCanBeCanceled != bIsCancelable)
{
bIsCancelable = bCanBeCanceled;
UAbilitySystemComponent* Comp = CurrentActorInfo->AbilitySystemComponent.Get();
if (Comp)
{
Comp->HandleChangeAbilityCanBeCanceled(GetAssetTags(), this, bCanBeCanceled);
}
}
}
这个函数中根据实例化策略和取消状态的变化,更新能力是否可以被取消的状态(bisCancelable)。如果 ASC 存在,调用其 HandleChangeAbilityCanBeCanceled 方法,通知系统该能力的取消状态已发生变化,并传递相关信息(资产本身的标签、GA本身和新的取消状态)。
void UGameplayAbility::SetShouldBlockOtherAbilities(bool bShouldBlockAbilities)
{
if (bIsActive && GetInstancingPolicy() != EGameplayAbilityInstancingPolicy::NonInstanced && bShouldBlockAbilities != bIsBlockingOtherAbilities)
{
bIsBlockingOtherAbilities = bShouldBlockAbilities;
UAbilitySystemComponent* Comp = CurrentActorInfo->AbilitySystemComponent.Get();
if (Comp)
{
Comp->ApplyAbilityBlockAndCancelTags(GetAssetTags(), this, bIsBlockingOtherAbilities, BlockAbilitiesWithTag, false, CancelAbilitiesWithTag);
}
}
}
如果能力处于激活状态,且实例化策略不是 NonInstanced,并且阻塞状态发生变化,则更新当前能力是否在阻塞其他能力的状态(bIsBlockingOtherAbilities)。如果ASC存在,则通过调用 ApplyAbilityBlockAndCancelTags 方法,通知系统根据当前能力的标签及其阻塞状态来决定哪些能力应该被阻止或取消
后边几个用到GetAssetTags的地方都是同上用到HandleChangeAbilityCanBeCanceled和ApplyAbilityBlockAndCancelTags两个方法。
还有就是在这个方法里用到了:
void UGameplayAbility::ApplyAbilityTagsToGameplayEffectSpec(FGameplayEffectSpec& Spec, FGameplayAbilitySpec* AbilitySpec) const
{
FGameplayTagContainer& CapturedSourceTags = Spec.CapturedSourceTags.GetSpecTags();
CapturedSourceTags.AppendTags(GetAssetTags());
// Allow the source object of the ability to propagate tags along as well
if (AbilitySpec)
{
CapturedSourceTags.AppendTags(AbilitySpec->GetDynamicSpecSourceTags());
const IGameplayTagAssetInterface* SourceObjAsTagInterface = Cast<IGameplayTagAssetInterface>(AbilitySpec->SourceObject);
if (SourceObjAsTagInterface)
{
FGameplayTagContainer SourceObjTags;
SourceObjAsTagInterface->GetOwnedGameplayTags(SourceObjTags);
CapturedSourceTags.AppendTags(SourceObjTags);
}
// Copy SetByCallerMagnitudes
Spec.MergeSetByCallerMagnitudes(AbilitySpec->SetByCallerTagMagnitudes);
}
}
将当前能力的标签(通过 GetAssetTags() 获取)添加到FGameplayEffectSpec的Tags中-->将来自能力实例的动态标签添加到FGameplayEffectSpec的Tags中-->将源对象的标签(如果源对象实现了 IGameplayTagAssetInterface)添加到FGameplayEffectSpec的Tags中-->合并与 SetByCaller 相关。
Set在本类里没找到别的用法。
2 取消带标签的能力 CancelAbilitiesWithTag
我看了看源码,哎发现这个翻译(也不知道是不是机翻)真不太好理解,我自己觉得应该这么翻译:按指定的标签取消能力
定义:
/** Abilities with these tags are cancelled when this ability is executed */
UPROPERTY(EditDefaultsOnly, Category = Tags, meta=(Categories="AbilityTagCategory"))
FGameplayTagContainer CancelAbilitiesWithTag;
找了一下发现都在调用下边这个函数的时候传入了这个参数,传在了形参CancelTags的位置:
(其实这个方法上边就涉及到了但是没仔细看)
void UAbilitySystemComponent::ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bEnableBlockTags, const FGameplayTagContainer& BlockTags, bool bExecuteCancelTags, const FGameplayTagContainer& CancelTags)
{
if (bEnableBlockTags)
{
BlockAbilitiesWithTags(BlockTags);
}
else
{
UnBlockAbilitiesWithTags(BlockTags);
}
if (bExecuteCancelTags)
{
CancelAbilities(&CancelTags, nullptr, RequestingAbility);
}
}
这个CancelAbilities的实现:
总结一下就是只要有WithTags这个参数里的任意标签,并且不能有WithoutTags这个参数里的任意标签就会取消对应的能力,当然是从当前激活的能力中遍历的,而且两个标签都为空好像也会取消。
void UAbilitySystemComponent::CancelAbilities(const FGameplayTagContainer* WithTags, const FGameplayTagContainer* WithoutTags, UGameplayAbility* Ignore)
{
ABILITYLIST_SCOPE_LOCK();
for (FGameplayAbilitySpec& Spec : ActivatableAbilities.Items)
{
if (!Spec.IsActive() || Spec.Ability == nullptr)
{
continue;
}
//跳过没有激活和无效的能力
const FGameplayTagContainer& AbilityTags = Spec.Ability->GetAssetTags();
bool WithTagPass = (!WithTags || AbilityTags.HasAny(*WithTags));
//如果WithTags为空,直接通过检查
//如果WithTags不为空,若包含WithTags中的任意标签也通过检查
bool WithoutTagPass = (!WithoutTags || !AbilityTags.HasAny(*WithoutTags));
//如果WithoutTags为空,直接通过检查
//如果WithoutTags不为空,若包含WithoutTags中的任意标签就不通过检查
if (WithTagPass && WithoutTagPass)//满足上述条件才实际取消
{
CancelAbilitySpec(Spec, Ignore);
}
}
}
这里虽然是1.16写的,但是为了区分哪部分是哪天写的就分p吧,之后会在这放后续的链接。