33. UE5 RPG使用增强输入激活GameplayAbility(三)

在前面的文章,我们实现了使用GameplayTag和InputAction的对应绑定的数据,并且添加到了增强输入映射的上下文中,实现了通过按键打印对应的GameplayTag,这只是我们基础需要制作的。目的主要是为了实现在GameplayAblity上面设置对应的Tag,在按下对应按键时,可以激活技能。
前面的步骤实现了,接下来,我们将在GA的基类上面增加一个GameplayTag配置属性,然后在给角色应用GA时,将GameplayTag设置给GA的实例,在触发InputAction的时候,通过遍历,找到被应用的GA里面有相同的Tag的GA,然后通过代码去触发。

实现

首先,我们需要再技能的基类上增加一个GameplayTag的配置属性,这样,我们就可以在技能蓝图上设置它所使用的GameplayTag了。

public:UPROPERTY(EditDefaultsOnly, Category="Input")FGameplayTag StartupInputTag;

在ASC中实现新的激活事件

接下来,我们要实现在运行时,应用GA时,需要在GamplayAbilitySpec身上将设置的GameplayTag存储下来。
DynamicAbilityTags是一个FGameplayTagContainer类型,它也是可以复制到服务器的,并且在创建GameplayAbilitySpec自动生成。
AbilitySpec.Ability是可以从Spec身上去获取实例的技能基类,并且它也是一个常量对象,我们在其身上设置的参数需要再常量身上去获取。

AbilitySpec.DynamicAbilityTags.AddTag(Cast<UGameplayAbilityBase>(AbilitySpec.Ability)->StartupInputTag);

我们修改ASC中添加技能的函数,它接收的参数是一个技能类的列表,然后遍历,我们在遍历里面通过类去创建Spec实例,如果Spec实例能够转换成我们创建的技能基类对象,那么,我们将基类对象身上设置的Tag设置到DynamicAbilityTags里面。
最后,我们将不会直接激活技能,而是只应用技能,然后通过按键触发技能。

void UAbilitySystemComponentBase::AddCharacterAbilities(const TArray<TSubclassOf<UGameplayAbility>>& StartupAbilities)
{for(const TSubclassOf<UGameplayAbility> AbilityClass : StartupAbilities){FGameplayAbilitySpec AbilitySpec = FGameplayAbilitySpec(AbilityClass, 1);if(const UGameplayAbilityBase* AbilityBase = Cast<UGameplayAbilityBase>(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的激活事件

接下来,我们将在PlayerController(PC主要储存角色操作的的相关内容的)里,触发操作后,调用ASC身上新创建的函数来触发技能激活。现在,我们还无法在PC身上获取ASC,所以,首先添加一个获取ASC的函数。
我们先创建一个变量存储ASC,然后再增加一个获取ASC的函数。

	UPROPERTY()TObjectPtr<UAbilitySystemComponentBase> AbilitySystemComponentBase;UAbilitySystemComponentBase* GetASC();

然后在函数实现这里,判断ASC是否被设置,如果没有被设置,将通过GAS的函数库去获取,这个静态函数将通过接口去获取

UAbilitySystemComponentBase* APlayerControllerBase::GetASC()
{if(AbilitySystemComponentBase == nullptr){AbilitySystemComponentBase = Cast<UAbilitySystemComponentBase>(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字符串打印,然后在一秒后触发技能关闭,并在屏幕打印技能结束
在这里插入图片描述

编辑运行,正常运行技能将不会被激活,而是在鼠标左键点击时触发
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/599901.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows命令行关机操作

cmd相关备忘 1. 导语2. Windows本命操作3. 实用命令集合3.1. 一段时间后关机3.2. 立即关机命令3.3. 一段时间后重启3.4. 休眠命令3.5. 取消指令 &#x1f609; 记录一些不常用有的时候很救命的cmd命令 1. 导语 不知道小伙伴们有么有遇到过这样尴尬的时候&#xff0c;电脑的鼠标…

Vue - 你会在同一个元素上使用v-for和v-if吗

难度级别:初级及以上 提问概率:50% 在初学者看来,v-for和v-if同时使用是非常方便的,二者共同使用的常见场景有两种。例如有两个列表,分别用于渲染学生数据和老师数据,然后有两个单选按钮,用于切换当前页面中需要展示学生列表还是老师列…

【CicadaPlayer】视频切换/音视频同时切换

G:\CDN\all_players\CicadaPlayer-github-0.44\mediaPlayer\SuperMediaPlayer.hCicadaPlayer https://github.com/alibaba/CicadaPlayer可以clone 整个仓库的历史 git clone --bare https://github.com/username/project.git整体架构 :根据这个更容易理解:切换就是judgeFunc…

机器视觉学习(十二)—— 绘制图形

目录 一、绘制函数参数说明 1.1 cv2.line(&#xff09;绘制直线 1.2 cv2.rectangle&#xff08;&#xff09;绘制矩形 1.3 cv2.circle&#xff08;&#xff09; 绘制圆形 1.4 cv2.ellipse&#xff08;&#xff09;绘制椭圆 1.5 cv2.polylines&#xff08;&#xff09;绘制…

牛客NC93 设计LRU缓存结构【hard 链表,Map Java】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/5dfded165916435d9defb053c63f1e84 思路 双向链表map最新的数据放头结点&#xff0c;尾节点放最老的数据&#xff0c;没次移除尾巴节点本地考察链表的新增&#xff0c;删除&#xff0c;移动节点参考答案Java im…

Java 基于微信小程序的校园请教小程序的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、10年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…

马斯克:AI或在2030年超越人类智力

据国外媒体报道&#xff0c;马斯克日前与奇点大学和XPRIZE基金会创始人彼得戴曼迪斯&#xff08;Peter Diamandis&#xff09;进行了线上对话。 在谈及人工智能的发展速度时&#xff0c;马斯克预计&#xff0c;按照当前的技术进步速度&#xff0c;到2030年AI的智力可能超越人类…

抖音引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域买单

抖音-引流私域转化模式1.0现场视频&#xff0c;从抖音源源不断把人加到私域&#xff0c;让加到私域的粉丝买单 课程内容&#xff1a;抖音引流私域转化模式1.0现场视频&#xff0c;从抖音源源不断把人加到私域买单 - 百创网-源码交易平台_网站源码_商城源码_小程序源码 01.第一…

zdpdjango_argonadmin Django后台管理系统中的常见功能开发

效果预览 首先&#xff0c;看一下这个项目最开始的样子&#xff1a; 左侧优化 将左侧优化为下面的样子&#xff1a; 代码位置&#xff1a; 代码如下&#xff1a; {% load i18n static admin_argon %}<aside class"sidenav bg-white navbar navbar-vertical na…

【javaWeb 原理篇】底层实现原理(快速学习配置原理,Bean管理)

Spring底层 配置优先级Bean管理获取beanBean的作用域第三方Bean SpringBoot原理起步依赖自动配置自动配置的原理自定义starter 配置优先级 Spring中的配置文件如果配置了相同的内容则根据配置优先级进行配置: application.properties>application.yml>application.yaml …

DLDP简介

定义 设备链路检测协议DLDP&#xff08;Device Link Detection Protocol&#xff09;用来监控光纤或铜质双绞线&#xff08;例如超五类双绞线&#xff09;的链路状态。如果发现单向链路存在&#xff0c;DLDP协议会根据用户配置&#xff0c;自动关闭或通知用户手工关闭相关接口…

pdf操作器(图片转文字、PDF转word、PDF拆分、图片jpg、png互转)

pdf操作器&#xff08;不用联网图片转文字、PDF转word、PDF拆分、图片jpg、png互转&#xff09;介绍目前该软件实现了以下功能 pdf转wordpdf拆分图片&#xff0c;图片导出在桌面的一个文件夹里图片合并为pdf压缩、转换图片格式&#xff08;jpg和png&#xff09;OCR图片转文字&…