北京公司网站制作哪家专业,wordpress的slider,宽屏公司网站源码php,南昌地宝网租房信息网在前面的文章#xff0c;我们实现了使用GameplayTag和InputAction的对应绑定的数据#xff0c;并且添加到了增强输入映射的上下文中#xff0c;实现了通过按键打印对应的GameplayTag#xff0c;这只是我们基础需要制作的。目的主要是为了实现在GameplayAblity上面设置对应的…在前面的文章我们实现了使用GameplayTag和InputAction的对应绑定的数据并且添加到了增强输入映射的上下文中实现了通过按键打印对应的GameplayTag这只是我们基础需要制作的。目的主要是为了实现在GameplayAblity上面设置对应的Tag在按下对应按键时可以激活技能。 前面的步骤实现了接下来我们将在GA的基类上面增加一个GameplayTag配置属性然后在给角色应用GA时将GameplayTag设置给GA的实例在触发InputAction的时候通过遍历找到被应用的GA里面有相同的Tag的GA然后通过代码去触发。
实现
首先我们需要再技能的基类上增加一个GameplayTag的配置属性这样我们就可以在技能蓝图上设置它所使用的GameplayTag了。
public:UPROPERTY(EditDefaultsOnly, CategoryInput)FGameplayTag StartupInputTag;在ASC中实现新的激活事件
接下来我们要实现在运行时应用GA时需要在GamplayAbilitySpec身上将设置的GameplayTag存储下来。 DynamicAbilityTags是一个FGameplayTagContainer类型它也是可以复制到服务器的并且在创建GameplayAbilitySpec自动生成。 AbilitySpec.Ability是可以从Spec身上去获取实例的技能基类并且它也是一个常量对象我们在其身上设置的参数需要再常量身上去获取。
AbilitySpec.DynamicAbilityTags.AddTag(CastUGameplayAbilityBase(AbilitySpec.Ability)-StartupInputTag);我们修改ASC中添加技能的函数它接收的参数是一个技能类的列表然后遍历我们在遍历里面通过类去创建Spec实例如果Spec实例能够转换成我们创建的技能基类对象那么我们将基类对象身上设置的Tag设置到DynamicAbilityTags里面。 最后我们将不会直接激活技能而是只应用技能然后通过按键触发技能。
void UAbilitySystemComponentBase::AddCharacterAbilities(const TArrayTSubclassOfUGameplayAbility StartupAbilities)
{for(const TSubclassOfUGameplayAbility AbilityClass : StartupAbilities){FGameplayAbilitySpec AbilitySpec FGameplayAbilitySpec(AbilityClass, 1);if(const UGameplayAbilityBase* AbilityBase CastUGameplayAbilityBase(AbilitySpec.Ability)){AbilitySpec.DynamicAbilityTags.AddTag(AbilityBase-StartupInputTag);GiveAbility(AbilitySpec); //只应用不激活// GiveAbilityAndActivateOnce(AbilitySpec); //应用技能并激活一次}}
}下面我们将在ASC上面增加两个函数一个是触发技能的悬停时触发的函数另一个是触发技能时按键离开时的。这两个函数都需要一个参数Tag去查找需要激活技能。 void AbilityInputTagHold(const FGameplayTag InputTag);void AbilityInputTagReleased(const FGameplayTag InputTag);在函数实现中我们首先判断传入的InputTag是否可用
if(!InputTag.IsValid()) return;然后遍历所有已经应用的技能GetActivatableAbilities()将返回一个可激活技能的列表
for(auto AbilitySpec : GetActivatableAbilities())然后我们将对Tag进行比对判断Spec上设置的Tag和传入的Tag是否相同如果相同将对技能处理。
if(AbilitySpec.DynamicAbilityTags.HasTagExact(InputTag))在技能悬停事件里面我们首先调用告知GameplayAbility此技能被触发按下事件
AbilitySpecInputPressed(AbilitySpec);防止技能重复被激活判断当前技能是否处于激活状态
if(!AbilitySpec.IsActive())尝试激活技能这里尝试激活是因为技能激活有很多限制你调用了激活只有在符合条件的情况下才真正被激活。
TryActivateAbility(AbilitySpec.Handle);而在Released函数内我们调用了下面函数告知技能按键事件被抬起。
AbilitySpecInputReleased(AbilitySpec);这两个事件会触发技能上面的回调来实现更多的逻辑我们可以在技能里面覆盖它来实现 virtual void InputPressed(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) override;virtual void InputReleased(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) override;
下面是在ASC实现的一个激活事件和取消事件的完整代码。
void UAbilitySystemComponentBase::AbilityInputTagHold(const FGameplayTag InputTag)
{if(!InputTag.IsValid()) return;for(auto AbilitySpec : GetActivatableAbilities()){if(AbilitySpec.DynamicAbilityTags.HasTagExact(InputTag)){AbilitySpecInputPressed(AbilitySpec);if(!AbilitySpec.IsActive()){TryActivateAbility(AbilitySpec.Handle);}}}
}void UAbilitySystemComponentBase::AbilityInputTagReleased(const FGameplayTag InputTag)
{if(!InputTag.IsValid()) return;for(auto AbilitySpec : GetActivatableAbilities()){if(AbilitySpec.DynamicAbilityTags.HasTagExact(InputTag)){AbilitySpecInputReleased(AbilitySpec);}}
}在PlayerController中修改并调用ASC的激活事件
接下来我们将在PlayerControllerPC主要储存角色操作的的相关内容的里触发操作后调用ASC身上新创建的函数来触发技能激活。现在我们还无法在PC身上获取ASC所以首先添加一个获取ASC的函数。 我们先创建一个变量存储ASC然后再增加一个获取ASC的函数。 UPROPERTY()TObjectPtrUAbilitySystemComponentBase AbilitySystemComponentBase;UAbilitySystemComponentBase* GetASC();然后在函数实现这里判断ASC是否被设置如果没有被设置将通过GAS的函数库去获取这个静态函数将通过接口去获取
UAbilitySystemComponentBase* APlayerControllerBase::GetASC()
{if(AbilitySystemComponentBase nullptr){AbilitySystemComponentBase CastUAbilitySystemComponentBase(UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetPawn()));}return AbilitySystemComponentBase;
}接着我们修改之前在PC里面触发的事件的函数之前实现到了打印Tag现在我们将其修改掉 不再打印
void APlayerControllerBase::AbilityInputTagPressed(FGameplayTag InputTag)
{GEngine-AddOnScreenDebugMessage(1, 3.f, FColor::Red, *InputTag.ToString());
}void APlayerControllerBase::AbilityInputTagReleased(FGameplayTag InputTag)
{GEngine-AddOnScreenDebugMessage(2, 3.f, FColor::Blue, *InputTag.ToString());
}void APlayerControllerBase::AbilityInputTagHold(FGameplayTag InputTag)
{GEngine-AddOnScreenDebugMessage(3, 3.f, FColor::Yellow, *InputTag.ToString());
}在函数里我们需要通过ASC去调用前面实现的激活技能函数但是我们还无法确保ASC不为空指针先做一下判断然后返回。
void APlayerControllerBase::AbilityInputTagPressed(FGameplayTag InputTag)
{// GEngine-AddOnScreenDebugMessage(1, 3.f, FColor::Red, *InputTag.ToString());
}void APlayerControllerBase::AbilityInputTagReleased(FGameplayTag InputTag)
{if(GetASC() nullptr) return;GetASC()-AbilityInputTagReleased(InputTag);
}void APlayerControllerBase::AbilityInputTagHold(FGameplayTag InputTag)
{if(GetASC() nullptr) return;GetASC()-AbilityInputTagHold(InputTag);
}测试
接下来我们编译代码解决bug然后打开UE找到之前我们做技能测试的蓝图上面已经可以设置Tag了。 我们设置一个使用鼠标左键触发当前技能 我们之前测试时在技能激活时触发ActivateAbility字符串打印然后在一秒后触发技能关闭并在屏幕打印技能结束
编辑运行正常运行技能将不会被激活而是在鼠标左键点击时触发