UE学习日志#1 GAS--GA中的Tag1

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吧,之后会在这放后续的链接。

UE学习日志#2 GAS--GA中的Tag2

<think> 嗯,用户想要了解在UE TS中使用GameplayTag来激活GameplayAbility的方法。根据提供的引用内容,尤其是引用[3]中提到的SetByCaller机制和GameplayTag的应用,我需要结合UEGameplayAbilitySystem知识来解答。 用户可能正在开发一个基于Unreal Engine的角色技能系统,需要动态触发技能。引用[3]提到的GameplayTag作为键值对的键,这正好是GAS中常用的激活机制。用户可能已经对蓝图中的GA激活有基础了解,现在想转向TypeScript实现(可能是用于UnrealJS或类似插件环境)。 考虑到用户提到了"UE TS",需要明确这是指Unreal Engine的TypeScript扩展插件(如Unreal.js),而非引擎原生支持。因此要强调API的差异性和插件限制。 核心回答应该聚焦三个层面: 1. 基础流程:如何通过ASC组件用Tag触发GA 2. TS实现要点:比如获取ASC组件、调用TryActivateAbilitiesByTag的方法差异 3. 注意事项:脚本插件与原生C++的性能差异,以及Tag的层级匹配特性 用户提供的引用[1][2]虽然关于支付和CI/CD,但与当前问题无关,可以忽略。但引用[3]的关键信息"以FGameplayTag为键"验证了Tag作为激活标识的用法,这个细节应该融入回答。 需要提醒用户注意:在TS中访问GAS API可能需要额外的插件支持,且网络同步逻辑必须服务端验证。如果用户实际想用蓝图,可能需要额外说明两者的结合方式。 最后生成的问题要覆盖延伸场景: - 如何传递激活参数(引用[3]提到的SetByCaller机制) - 多人游戏中的权限问题 - 常见调试痛点(比如Tag不匹配) </think> 在Unreal Engine的TypeScript环境中,使用GameplayTag激活GameplayAbility(GA)的核心流程如下(需配合GameplayAbilitySystem组件): ### 实现步骤 1. **GameplayTag配置** - 在`Project Settings > GameplayTags`中创建标签(如`Ability.Activate.Fireball`) -GA蓝图中绑定标签:`GameplayAbility类默认属性 > Ability Tags > 添加对应Tag` 2. **TS端激活逻辑** ```typescript // 获取Actor的AbilitySystemComponent const asc = this.actor.getComponentByClass(AbilitySystemComponent) as AbilitySystemComponent; // 通过Tag激活GA if (asc) { // 创建GameplayTag容器 const tagContainer = new GameplayTagContainer(); tagContainer.addTagFast(GameplayTag.RequestGameplayTag("Ability.Activate.Fireball")); // 触发GA激活(需注意网络角色权限) asc.tryActivateAbilitiesByTag(tagContainer, true); } ``` 3. **网络同步处理(重要)** 在多人游戏中需验证执行权限: ```typescript if (GetWorld().GetNetMode() !== NM_Client) { // 服务端执行逻辑 } else { // 客户端发送RPC请求 this.serverActivateAbility(tagContainer); } ``` ### 关键机制 1. **Tag匹配原理** GA的`AbilityTags`与传入的`ActivationTag`需精确匹配或通过`GameplayTagContainer`的层级匹配(如`Ability.Activate.*`可匹配所有子标签)[^3]。 2. **激活参数传递** 可通过`GameplayEventData`附加参数: ```typescript const eventData = new GameplayEventData(); eventData.optionalObject = this.projectileClass; // 传递投射物类 asc.handleGameplayEvent(tagContainer, eventData); ``` 3. **蓝图与TS交互** 可在TS中声明UFUNCTION供蓝图调用: ```typescript @BlueprintCallable public activateAbilityByTag(tag: string): void { //...TS实现代码 } ``` > ⚠️ **注意事项** > - 必须在GA的`CanActivateAbility`函数中实现Tag有效性验证 > - 客户端激活需通过`ServerTryActivateAbility` RPC > - UE5的`GameplayTag`需通过`RequestGameplayTag()`获取引用 ### 调试技巧 1. 控制台命令:`showdebug abilitysystem` 查看激活状态 2. 使用`GameplayTag.DebugPrintNetTags()`输出当前Tag 3. 监听激活失败事件: ```typescript asc.onAbilityFailed.add((tag) => { console.error(`GA激活失败: ${tag.toString()}`); }); ``` 相关问题: 1. 如何在GA激活时通过SetByCaller传递动态参数?[^3] 2. 如何实现GameplayTag的层级继承关系(如`Ability.Activate.Fireball`继承`Ability.Activate`)? 3. 多人游戏中客户端预测激活GA的正确同步流程是什么? 4. 如何通过DataAsset配置TagGA的映射关系?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值