虚幻四Gameplay Ability System入门(5)-冲刺奔跑和深入Attribute_getgameplayattributevaluechangedelegate-程序员宅基地

技术标签: 游戏引擎  虚幻五  虚幻 Gameplay Ability System  游戏  游戏开发  

在这篇文章开始前,先分享一个惨痛的经历,就因为在虚幻四的源码中加了两句注释,项目的编译就走向了拥有3000+ Errors的不归路 T T,这是啥原理啊。

这次我们要实现的功能是角色的冲刺奔跑,操作就是点击shift后角色的移动速度会增加。这个能力的实现应该是挺简单的,但是我会扩展一部分的GAS源码,深入一下GAS的Attribute,希望能够帮助到一部分读者。有问题也希望大家可以在评论或者私信告诉我。

接下来进入正题,首先还是讲解一下加速跑的实现过程:

  1. shift点击后activiate加速跑技能。
  2. 加速跑技能会添加一个GE,这个GE会增加角色Move Speed Attribute
  3. 角色的Character.h/cpp中添加function,将它与move speed的change delegate绑定在一起。在该function中会提高角色Movement Component的移动速度。
  4. shift键松开后发送一个Gameplay Event告诉奔跑能力End Ability。

添加MoveSpeed Attribute

打开AttributeSetBase.h/cpp,然后添加MoveSpeed Attribute。这个操作流程已经重复无数次啦,相信能看到这里的读者应该都掌握了,我就不重复了。

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Attributes", ReplicatedUsing=OnRep_MoveSpeed)
	FGameplayAttributeData MoveSpeed;
	ATTRIBUTE_ACCESSORS(UAttributeSetBase, MoveSpeed);

UFUNCTION()
	virtual void OnRep_MoveSpeed(const FGameplayAttributeData& OldMoveSpeed);

但是我们创建了这么多次的Attibute,还不了解它的数据结构是咋样的,打开AttributeSetBase的父类AttributeSet.h。我删除了其它代码,重要的是下面的部分。它表明一个Attribute中有两个float值Base Value,和Current Value。

USTRUCT(BlueprintType)
struct GAMEPLAYABILITIES_API FGameplayAttributeData
{
    
	protected:
	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	float BaseValue;

	UPROPERTY(BlueprintReadOnly, Category = "Attribute")
	float CurrentValue;
};

为什么属性需要Base和Current两个值呢?根据大佬的文档https://github.com/tranek/GASDocumentation#concepts-asc, Base Value的值属性的基础,它是永久(permanent)的,Current Value相反,它是临时的。

打个比方,比如我们要实现的加速奔跑,它改变的是实际是Current Value,当加速效果结束后,Current Value就会降低回默认值。类似的效果还有某种buff会暂时提高角色的生命值或者护甲等等,这个buff改变的就是这种属性的Current Value。

相反,当角色的生命值被攻击后扣除,它改变的就是Health属性的Base Value,可以把攻击造成的伤害当作是永久改变的,毕竟没有其它影响角色的生命值就不会发生改变了。

那么哪些操作会改变Base值,哪些会改变Current值呢?打开一个Gameplay Effect,然后点击Duration Policy,可以看到有三种模式,其中Instant改变的是Base值,Infinite和Has Duration改变的是Current Value,因为某种意义上这两个效果是有持续时间的。但是Duration policy的特殊情况,当它存在period的时候,它改变的同样是Base值,因为Period Duration可以理解为每一个period触发一次的instant。
1.PNG

创建完毕后,记得需要给予MoveSpeed Attribute一个初值。
2.PNG

实现Sprint技能

创建Gameplay Ability命名为GA_Sprint,作为加速跑技能。创建Gameplay Effect命名为GE_Sprint_SpeedUp负责提高移动速度。

3.png

打开GE_Sprint_SpeedUp。技能效果为永久(Infinite)提高MoveSpeed属性2000,同时需要给该GE添加Tag为Ability.Sprint.SpeedUp

5.PNG
5.1.png

然后打开GA_Sprint。Sprint的流程为对拥有该技能的角色申请一个GE,就是刚才我们创建的那个。然后等待Gameplay Event,这个事件带有标签Ability.Sprint.EndAbility。接收到事件后,移除带有Ability.Sprint.SpeedUp标签的GE,然后结束能力。
4.PNG

打开角色蓝图。

添加能力(Give Ability),绑定输入。这里当shift松开后,会向自己发送一个Gameplay Event,带有标签Ability.Sprint.EndSprint。这就是在能力中等待的事件。
6.PNG

MoveSpeed Change Delegate

打开CharacterBase.h/cpp,然后创建function

void OnMoveSpeedAttributeChanged(const FOnAttributeChangeData& Data);

实现,当接收到发生改变的Attribute后,改变MovementComponent的MaxWalkSpeed,注意,这里不能直接通过GetCharacterMovement()修改移动速度。

void ACharacterBase::OnMoveSpeedAttributeChanged(const FOnAttributeChangeData& Data)
{
    
	UCharacterMovementComponent *MovementPtr =  Cast<UCharacterMovementComponent>(GetCharacterMovement());
	MovementPtr->MaxWalkSpeed = Data.NewValue;
}

然后在BeginPlay中将该function与MoveSpeed的Change Delegate绑定。

void ACharacterBase::BeginPlay()
{
    
	Super::BeginPlay();

	if(AbilitySystem)
	{
    
		AbilitySystem->GetGameplayAttributeValueChangeDelegate(UAttributeSetBase::GetMoveSpeedAttribute())
		.AddUObject(this, &ACharacterBase::OnMoveSpeedAttributeChanged);
	}
}

响应Attribute的改变

刚才实现的相应Attribute改变实际上发生在属性值已经改变后,但是我们处理最大生命值,生命值不能小于0等事件不适合在角色代码里实现,实际上GAS系统提供了接口可以在属性值发生改变前进行处理。

重写两个方法。PreAttributeChange负责在属性值的Current Value发生改变前进行处理。PostGameplayEffectExecute发生在Base Value发生改变前。

virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
	
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;

我们可以在这里设置属性值的范围。比如下图的处理就可以让生命值保持在0到100之间。

void UAttributeSetBase::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
    
	Super::PostGameplayEffectExecute(Data);

	if(Data.EvaluatedData.Attribute == GetHealthAttribute())
	{
    
		SetHealth(FMath::Clamp(GetHealth(), 0.0f, 100.0f));
	}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_38110586/article/details/116122242

智能推荐

【愚公系列】2023年07月 Python自动化办公之win32com操作excel-程序员宅基地

文章浏览阅读6k次。python中能操作Excel的库主要有以下9种:本文主要针对win32com读取 写入 修改 操作Excel进行详细介绍win32com是Python的一个模块,它提供了访问Windows平台上的COM组件和Microsoft Office应用程序的能力。通过该模块,Python程序可以与Windows平台上的其他应用程序交互,例如实现自动化任务、自动化报告生成等功能。_win32com

sql审核工具 oracle,Oracle SQL Developer工具-程序员宅基地

文章浏览阅读326次。Oracle SQL Developer工具下载解压了Oracle SQL Developer工具,运行时,启动不了,报错信息如下:---------------------------Unable to create an instance of the Java Virtual MachineLocated at path:\jdk\jre\bin\client\jvm.dll--------..._开源oracle sql审核工具

百度实习面经2022-4-24(第一次面试,暂时只面了一场,感觉人无了)_百度实习面试-程序员宅基地

文章浏览阅读3.5k次。百度实习面经2022-4-26(第一次面试,只面了一场,感觉人无了)_百度实习面试

ipv6隧道穿越ipv4互联实验-程序员宅基地

文章浏览阅读142次。实验名称:ipv6隧道穿越ipv4互联实验实验目的:配置隧道让ipv6能穿越ipv4实现互联实验拓扑图: 实验详细配置步骤:R1Router&gt;enRouter#conf tRouter(config)#line con 0Router(config-line)#logg syncRouter(config-line)#exitRouter(co...

Eclipse - Create a new Source File / Header File_eclipse新建源文件-程序员宅基地

文章浏览阅读576次。Eclipse - Create a new Source File / Header File_eclipse新建源文件

【C语言学习】数组名的实质-程序员宅基地

文章浏览阅读1.5k次,点赞14次,收藏15次。一般情况下,数组名的本质是数组首元素的地址,只有两种情况下,即遇到sizeof和&是数组名的代表的是整个数组。_数组名

随便推点

达梦数据库--学习总结-程序员宅基地

文章浏览阅读697次。达梦概述:1. 达梦:达梦数据库管理系统是达梦公司推出的具有完全自主知识产权的高性能数据库管理系统,简称DM。2. 2019年新一代达梦数据库管理系DM8发布。(二)特点:1. 通用性:达梦数据库管理系统兼容多种硬件体系,可运行于X86、X64、SPARC、POWER等硬件体系之上。2. 高性能:支持列存储、数据压缩、物化视图等面向联机事务分析场景的优化选项。3. 高可用:可配置数据守护系统(主备),自动快速故障恢复,具有强大的容灾处理能力。_达梦数据库

神经网络(优化算法)_nnet-程序员宅基地

文章浏览阅读1.2w次。神经网络(优化算法)人工神经网络(ANN),简称神经网络,是一种模仿生物神经网络的结构和功能的数学模型或计算模型。神经网络由大量的人工神经元联结进行计算。大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自适应系统。现代神经网络是一种非线性统计性数据建模工具,常用来对输入和输出间复杂的关系进行建模,或用来探索数据的模式。人工神经网络从以下四个方面去模拟人的智能行为:_nnet

<video>标签及属性说明_video标签-程序员宅基地

文章浏览阅读5.5w次,点赞56次,收藏300次。实例HTML <video> 标签一段简单的 HTML5 视频:<video src="video.mp4" controls="controls">您的浏览器不支持 video 标签。</video>属性性 值 描述 autoplay autoplay 如果出现该属性,则视频在就绪后马上播放。 controls controls 如果出现该属性,则向用户显示控件,比如播放按钮。 height_video标签

LRU算法四种实现方式介绍_lru 实现-程序员宅基地

文章浏览阅读2.3k次。LRU全称是LeastRecently Used,即最近最久未使用的意思。LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。实现LRU1. 用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项的时候,先把数组中存在的数据项的时间戳自增,并将新数据项的时间戳置为0并插入到数组中。每次访问数组中的数据项的时候,将被访问的数据项的时间戳置为0。当数组空间已..._lru 实现

anaconda在cmd运行时报错OSError: [WinError 123] 文件名、目录名或卷标语法不正确解决办法_oserror: [winerror 123] 文件名、目录名或卷标语法不正确。: '"c:\\pr-程序员宅基地

文章浏览阅读3.4k次,点赞12次,收藏8次。在网上看到其他帖子说删除环境变量什么的,试了试并没有成功,后来发现环境变量里面有些变量写到一行里面了,只需要把这些环境变量变成一行一行的。比如我之前的环境变量是这样的。把它变成下面这样就好了。_oserror: [winerror 123] 文件名、目录名或卷标语法不正确。: '"c:\\program file

unity 2021.3.6f1 报错 dependencies manifest(Microsoft.NetCore.App.deps.json)was not found_unitydependencies-程序员宅基地

文章浏览阅读2.9k次。dependencies manifest (Microsoft.NETCore.App.deps.json) was not found. runtime.win-x64.Microsoft.NETCore.App', version: '5.0.3-servicing.21072.12'_unitydependencies

推荐文章

热门文章

相关标签