45. UE5 RPG 增加角色受击反馈

在前面的文章中,我们实现了对敌人的属性的初始化,现在敌人也拥有的自己的属性值,技能击中敌人后,也能够实现血量的减少。
现在还需要的就是在技能击中敌人后,需要敌人进行一些击中反馈,比如敌人被技能击中后,可以播放击中的动画,并且显示伤害值。
我们在这一篇文章中,实现敌人被英雄的技能击中时,会播放受击动画,并且在敌人身上添加一个受击标签,角色在受击时,根据标签判断设置移动速度

设置角色受击标签

首先,我们实现在敌人身上添加标签,我们需要通过GE去添加。
创建一个新的GE
在这里插入图片描述
命名为GE_HitReact
在这里插入图片描述
在里面设置持续时间设置无限时间,我们在技能里面应用它,然后在技能结束是,将其清除
在这里插入图片描述
现在,我们还没有受击对应的标签,在c++里添加一个

FGameplayTag Effects_HitReact; //受击 标签
GameplayTags.Effects_HitReact = UGameplayTagsManager::Get()
	.AddNativeGameplayTag(
		FName("Effects.HitReact"),
		FString("受到攻击时,赋予的标签")
	);

然后在GE里面使用TargetTagsGameplayEffectComponent组件,它可以将标签应用到目标角色身上
在这里插入图片描述

角色监听标签并设置移动速度

我们接下来实现对受击标签的监听,在源码中,受击标签会返回监听的标签和添加标签的个数
在这里插入图片描述
在这里插入图片描述
我们创建一个委托回调函数

void HitReactTagChanged(const FGameplayTag CallbackTag, int32 NewCount);

并创建变量来表示角色是否处于受击状态

UPROPERTY(BlueprintReadOnly, Category="Combat")
bool bHitReacting = false; //当前是否处于被攻击状态

UPROPERTY(BlueprintReadOnly, Category="Combat")
float BaseWalkSpeed = 250.f; //当前角色的最大移动速度

在AEnemyBase::BeginPlay()中,我们设置对监听函数的回调

AbilitySystemComponent->RegisterGameplayTagEvent(FMyGameplayTags::Get().Effects_HitReact, EGameplayTagEventType::NewOrRemoved)
 .AddUObject(this, &ThisClass::HitReactTagChanged);

如果数量大于0,则将其的移动速度设置为0

void AEnemyBase::HitReactTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
	bHitReacting = NewCount > 0;
	GetCharacterMovement()->MaxWalkSpeed = bHitReacting ? 0.f : BaseWalkSpeed;
}

创建一个受击技能,并应用GE

接下来,我们创建一个新的技能,用来实现受击,是的,受击也是角色的技能。在角色受到攻击时,将触发角色受击技能来实现受击效果。
在这里插入图片描述
在技能触发时,我们将受击标签添加到角色身上,这样,之前监听角色标签的回调函数将触发,并设置移动速度,我们并将句柄保持,在技能结束时,方便移除GE
在这里插入图片描述

实现设置角色的受击蒙太奇动画

接下来,我们将实现角色受击时播放蒙太奇动画,为了保证通用性,我们将其设置为一个函数,并设置到战斗接口中,这样只需要在战斗接口中获取对应角色的蒙太奇即可。(每个角色的受击动画不一定一样)
首先在战斗接口中实现一个函数,这函数可以在蓝图中被覆写,也可以在蓝图中调用。

UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
UAnimMontage* GetHitReactMontage(); //获取受击蒙太奇动画

然后,我们在角色的基类里,对这个函数进行覆写。

virtual UAnimMontage* GetHitReactMontage_Implementation() override;

并增加一个参数用于设置蒙太奇

UPROPERTY(EditAnywhere, Category="Combat")
TObjectPtr<UAnimMontage> HitReactMontage;

在函数实现这里,直接返回蒙太奇

UAnimMontage* ACharacterBase::GetHitReactMontage_Implementation()
{
	return HitReactMontage;
}

接着在技能里面,将ASC控制的角色转换为战斗接口,从战斗接口调用函数获取到角色设置的蒙太奇进行播放
在这里插入图片描述
接下来就是基于动画创建蒙太奇
在这里插入图片描述
并将蒙太奇设置到角色身上,用于函数返回。
在这里插入图片描述

激活受击技能

接下来,就是我们实现对技能的激活,和上一篇一样,我们创建了一个敌人的DataAsset,我们希望可以将敌人所拥有的初始技能都设置在数据里,并在初始化时使用。
在CharacterClassInfo.h里增加一个参数,用于设置创建敌人时所拥有的初始技能

	UPROPERTY(EditDefaultsOnly, Category="Common Class Defaults")
	TArray<TSubclassOf<UGameplayAbility>> CommonAbilities;

之前英雄角色初始化技能我们创建了一个应用技能的函数
在这里插入图片描述
它是创建技能实例,并给与ASC,我们将给敌人创建一个通用的函数,并放到函数库中
在这里插入图片描述
在函数技能库里新增一个函数用于初始化角色技能

//初始化角色的技能
UFUNCTION(BlueprintCallable, Category="MyAbilitySystemLibrary|CharacterClassDefaults")
static void GiveStartupAbilities(const UObject* WorldContextObject, UAbilitySystemComponent* ASC);

函数实现就是获取到数据资产里面的技能列表,创建实例并给与角色

void UMyAbilitySystemBlueprintLibrary::GiveStartupAbilities(const UObject* WorldContextObject, UAbilitySystemComponent* ASC)
{
	//获取到当前关卡的GameMode实例
	const AMyGameModeBase* GameMode = Cast<AMyGameModeBase>(UGameplayStatics::GetGameMode(WorldContextObject));
	if(GameMode == nullptr) return;

	const AActor* AvatarActor = ASC->GetAvatarActor();

	//从实例获取到关卡角色的配置
	UCharacterClassInfo* CharacterClassInfo = GameMode->CharacterClassInfo;

	//遍历角色拥有的技能数组
	for(const TSubclassOf<UGameplayAbility> AbilityClass : CharacterClassInfo->CommonAbilities)
	{
		FGameplayAbilitySpec AbilitySpec = FGameplayAbilitySpec(AbilityClass, 1); //创建技能实例
		ASC->GiveAbility(AbilitySpec); //只应用不激活
	}
}

在敌人基类里,开始事件时,我们调用函数库的初始化技能函数,将技能应用到角色身上

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

	//设置角色的初始移动速度
	GetCharacterMovement()->MaxWalkSpeed = BaseWalkSpeed;

	//初始化角色的ASC
	InitAbilityActorInfo();

	//初始化角色的技能
	UMyAbilitySystemBlueprintLibrary::GiveStartupAbilities(this, AbilitySystemComponent);
	...

方便测试,在PostGameplayEffectExecute函数里,之前设置血量下面有判断,我们在角色没有被击杀时,让其触发受击技能。激活我们是使用的根据标签激活,它需要传入一个FGameplayTagContainer 类型的参数。

	if(Data.EvaluatedData.Attribute == GetIncomingDamageAttribute())
	{
		const float LocalIncomingDamage = GetIncomingDamage();
		SetIncomingDamage(0.f);
		if(LocalIncomingDamage > 0.f)
		{
			const float NewHealth = GetHealth() - LocalIncomingDamage;
			SetHealth(FMath::Clamp(NewHealth, 0.f, GetMaxHealth()));

			const bool bFatal = NewHealth <= 0.f; //血量小于等于0时,角色将会死亡
			if(!bFatal)
			{
				FGameplayTagContainer TagContainer;
				TagContainer.AddTag(FMyGameplayTags::Get().Effects_HitReact);
				Props.TargetASC->TryActivateAbilitiesByTag(TagContainer); //根据tag标签激活技能
			}
		}
	}

接下来,编译代码,打开UE,将我们之前创建的受击技能设置到数据资产中
在这里插入图片描述
我们将使用标签激活技能,所以,在技能里,还需要将受击标签设置给技能
在这里插入图片描述
我们不需要在每次激活时创建一个新的实例,只需要一个角色生成一个实例重复利用即可。
在这里插入图片描述
由于它一个角色对应一个单例,每次触发都是相同的实例,所以,我们需要在其播放完成后,将其结束,才可以触发,所以,在敌人的受击动画播放完成后,我们需要将敌人身上的受击标签清楚(如果GE添加的,只需要将对应的GE清除,标签也会随着清除)并结束技能。
在这里插入图片描述
接下来,就是测试效果,我们攻击敌人,看看其是否能够播放动画。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习中的注意力机制二(Pytorch 16)

一 Bahdanau 注意力 通过设计一个 基于两个循环神经网络的编码器‐解码器架构&#xff0c;用于序列到序列学习。具体来说&#xff0c;循环神经网络编码器将长度可变的序列转换为固定形状的上下文变量&#xff0c;然后循环神经网络 解码器根据生成的词元和上下文变量按词元生成…

meshlab: pymeshlab计算两个模型的布尔交集(mesh boolean intersection)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本案例以两个圆环为例。 左侧为两个圆环&#xff0c;右上是重叠&#xff0c;右下是圆…

引流源码短剧搜索前端源码+内附搜索API

引流源码短剧搜索前端源码内附搜索API&#xff0c;全网短剧搜索前端源码分享&#xff0c;文末附API及使用详解 内含7000短剧资源(不支持在线播放&#xff09;&#xff0c;毕竟搞在线播放挺烧钱的[阴险] 源码直接上传虚拟主机或服务器即可使用&#xff0c;无需其他配置&#x…

jvm 马士兵 01 JVM简介,class文件结构

01.JVM是什么 JVM是一个跨平台的标准 JVM只识别class文件&#xff0c;符合JVM规范的class文件都可以被识别 u1 是一个字节 u2是两个字节

使用网络用户命令行工具的/passwordreq:yes

提示:"新建域时&#xff0c;本地administrator帐户将成为域administrator账户。无法新建域&#xff0c;因为本地administrator账户密码不符合要求。 目前&#xff0c;本地administrator账户不需要密码。我们建议您使用网络用户命令行工具的/passwordreq:yes选项获得该账户…

AI图书推荐:ChatGPT在真实商业世界中的应用

《ChatGPT在真实商业世界中的应用》 (Unleashing The Power of ChatGPT: A Real World Business Applications)首先概述了ChatGPT及其在对话式人工智能领域的影响。接着&#xff0c;你将深入了解ChatGPT的技术方面&#xff0c;理解机器学习算法和自然语言处理如何在后台工作。然…

鸿蒙ArkTs开发,仿抖音个人中心header 下拉放大

如果是iOS 或者android 上实现&#xff0c;可以用Scollview 的contentOffset 来实现&#xff0c;然而在鸿蒙ets中该如何实现&#xff1f;废话不多说开始撸代码 第一步、实现一个header // 创建header&#xff0c;准备一张背景图片BuilderHeaderBuilder(){Column() {Row() {Ima…

社交媒体数据恢复:爱聊

爱聊数据恢复方法 在爱聊的使用过程中&#xff0c;如果遇到数据丢失的情况&#xff0c;可以尝试以下几种方法来恢复数据。 1. 硬盘坏道检测与修复 如果问题是由于硬盘坏道导致的&#xff0c;可以按照以下步骤进行操作&#xff1a; 找到需要修复的坏道磁盘&#xff1a;首先&…

js模块化:修改导入模块的内容,会有影响吗?

起因 element-ui的popper组件相关的层级&#xff0c;是使用popup-manager来统一管理的。 之前试图在自己的组件里导入并使用element-ui的popup-manager&#xff0c;但是层级老是和element-ui组件的层级冲突&#xff0c;看了下源码&#xff0c;竟意外发现&#xff0c;使用popu…

基于若依框架搭建网站的开发日志(一):若依框架搭建、启动、部署

RuoYi&#xff08;基于SpringBoot开发的轻量级Java快速开发框架&#xff09; 链接&#xff1a;开源地址 若依是一款开源的基于VueSpringCloud的微服务后台管理系统&#xff08;也有SpringBoot版本&#xff09;&#xff0c;集成了用户管理、权限管理、定时任务、前端表单生成等…

You don’t have permission.

The document “XXX” could not be saved. You don’t have permission. 1.查看修改了iOS系统库导致的, 根据提示, 进入到"XXX"文件中, 然后commandz回退/取消 2. Xcode 调试遇到的报错&#xff08;持续更新&#xff09;

治疗耳鸣患者案例分享第二期

“患者耳鸣20年了&#xff0c;目前耳朵没有堵或者胀的感觉&#xff0c;但是偶尔有点痒&#xff0c;平时会有头晕头胀这种情况&#xff0c;然后头晕是稍微晕炫一下。然后头疼是经常有的&#xff0c;头胀不经常。” 患者耳鸣持续20年&#xff0c;虽然耳朵没有堵或胀的感觉&#x…

书生浦语训练营第三次课笔记:XTuner 微调 LLM:1.8B、多模态、Agent

Finetune 简介 两种Finetune范式&#xff1a;增量预训练微调、指令跟随微调 微调数据集 上述是我们所期待模型回答的内容&#xff0c;在训练时损失的计算也是基于这个。 训练数据集看起来是这样&#xff0c;但是真正喂给模型的&#xff0c;是经过对话模板组装后的 下图中&…

防火墙的基本概念

我们在 TCP/IP协议四层模型与OSI七层模型 的最后说过&#xff0c;在四层模型中每一层都会有对应的风险&#xff0c;而防火墙就是来阻断这些风险的工具。 防火墙的基本功能 防火墙的分类 目前没有权威而明确的分类 按照实现方式&#xff1a; 硬件防火墙软件防火墙 按照部署…

HNU-人工智能-实验1-A*算法

人工智能-实验1 计科210x 甘晴void 一、实验目的 掌握有信息搜索策略的算法思想&#xff1b; 能够编程实现搜索算法&#xff1b; 应用A*搜索算法求解罗马尼亚问题。 二、实验平台 课程实训平台https://www.educoder.net/shixuns/vgmzcukh/challenges 三、实验内容 3.…

高扬程水泵助力森林消防,守护绿色生命线/恒峰智慧科技

随着人类社会的不断发展&#xff0c;森林资源的保护和管理变得越来越重要。然而&#xff0c;森林火灾却时常威胁着这一宝贵资源。为了有效应对森林火灾&#xff0c;提高灭火效率&#xff0c;高扬程水泵在森林消防中发挥了重要作用。本文将重点介绍高扬程水泵在森林消防中的应用…

AI终端设备的自动化分级

摘要&#xff1a; AI智体被定义为感知环境、做出决策和采取行动的人工实体。 受SAE&#xff08;汽车工程师学会&#xff09;自动驾驶6个级别的启发&#xff0c;AI智体也根据效用和强度进行分类&#xff0c;分为以下几个级别&#xff1a; L0——无AI&#xff0c;有工具&#xf…

机器学习中线性回归算法的推导过程

线性回归是机器学习中监督学习中最基础也是最常用的一种算法。 背景&#xff1a;当我们拿到一堆数据。这堆数据里有参数&#xff0c;有标签。我们将这些数据在坐标系中标出。我们会考虑这些数据是否具有线性关系。简单来说 我们是否可以使用一条线或者一个平面去拟合这些数据的…

力扣每日一题111:二叉树的最小深度

题目 简单 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2示例 2&#x…

SpringCloud生态体系介绍

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的开发风格做到一键启动和部署。 必要说…