ARPG----C++学习记录05 Section12 动画蒙太奇,收拿剑,MetaSound,调整动画

代码更新

https://github.com/BAOfanTing/ARPG_Game_Code/commit/c629270e49496ba1bcbaf03780d23c1842ca5e7a

Animation Montages动画蒙太奇

蒙太奇的工作流程

新建一个鼠标左键的按键映射,下载一些攻击动画,重定向给我们的人物,新建一个动画蒙太奇,放入动画

然后在动画蓝图里插入一个Slot节点再在人物的蓝图里这样设置,就能点击产生攻击动画

使用C++来播放蒙太奇

新建函数Attack,绑定,定义一个蒙太奇变量

首先获取动画实例,判断动画实例和蒙太奇动画是不是空指针,用一个随机数来选择播放的蒙太奇动画,最后还需要在蓝图里设置攻击蒙太奇

优化攻击动画

现在一直点击鼠标会打断上一次的攻击重复播放需要更改。把播放蒙太奇的代码封装成一个函数,随后新定义一个角色动作状态的枚举,先判断能否进行攻击,进入后设置攻击状态无法重置攻击。

UENUM(BlueprintType)
enum class EActionState:uint8
{
	EAS_Unoccupied UMETA(DisplayName = "Unoccupied"),
	EAS_Attacking UMETA(DisplayName = "Attacking"),
	EAS_Equipping UMETA(DisplayName = "Equipping")
};

void ACharacter01::Attack()
{	
	if (CanAttack())
	{
		PlayAttackMontage();
		ActionState = EActionState::EAS_Attacking;
	}
}

void ACharacter01::PlayAttackMontage()
{
	// 获取角色的骨架并检查是否存在动画实例以及攻击蒙太奇(Montage)
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	if (AnimInstance && AttackMontage)
	{	// 在动画实例上播放攻击蒙太奇
		AnimInstance->Montage_Play(AttackMontage);
		// 生成一个随机数,选择攻击动作的不同部分
		const int32 Selection = FMath::RandRange(0, 1);
		FName SectionName = FName();
		// 根据随机数选择不同的攻击部分
		switch (Selection)
		{
		case 0:
			SectionName = FName("Attack1");
			break;
		case 1:
			SectionName = FName("Attack2");
			break;
		default:
			break;
		}
		// 跳转到所选的攻击部分
		AnimInstance->Montage_JumpToSection(SectionName, AttackMontage);
	}
}

但是上边的方法只能攻击一次,使用动画通知来知道动画已经播放完了,在蒙太奇里边新建两个notify

新建一个攻击结束函数,将函数和变量都暴露给蓝图,在动画蓝图中

在动画蓝图中当动画结束时直接调用这个函数,这样我们就能多次攻击不卡顿

武器漂浮,走动不攻击

新建一个枚举类来判断武器是否被拿在手上,定义初始转态

UENUM(BlueprintType)
enum class EItemState : uint8
{
	EIS_UnOnHand UMETA(DisplayName="UnOnHand"),
	EIS_OnHand UMETA(DisplayName = "OnHand")
};

在tick函数里添加判断当物体不被拿起时漂浮,在回到武器cpp在equip的函数里将ItemState就设置完成了

// 每帧都会被调用
void Aitem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// 记录经过的总时间
	RunningTime += DeltaTime;
	//当物体不被拿起时漂浮
	if (ItemState == EItemState::EIS_UnOnHand)
	{
		AddActorWorldOffset(FVector(0.f,0.f,TransformedSin()));
	}
}

走动不攻击只需要判断是否在攻击状态,如果在的话就不接收移动的值

挥剑声音、喘息声音

进入攻击的动画蓝图添加一个播放声音的notify,也可以在蒙太奇中放入,

为了更改声音,可以创建一个soundcue

在插件里打开MetaSound,新建一个

新建一个变量,修改type改为whoosh,使用随机函数来让时长和声音变大变小

创建一个人物的喘息声音,传入的声音是一个数组,选中10个声音,最后把两个声音都加入蒙太奇

脚步声和粒子效果

跟喘息声一样,导入18个声音文件进行制作,进入跑步动画,加上脚步和袋子碰撞的声音,并且从包里将粒子效果copy并且绑定左右脚。把跳跃等动作都加上音效

修改一下脚的位置

攻击时脚会挪开是因为ik——foot没有对应上脚的位置,所以要进行修改

将每个脚位置的transform给ik就可以改正

收剑,拿出剑

下载拿收剑和不拿剑待机的动画,导入重定向,新建蒙太奇。回到人物头文件新建进入条件,装备蒙太奇变量,播放函数

//能够卸下武器
bool CanDisarm();
bool Canarm();
void PlayEquipMontage(FName SectionName);


UPROPERTY(EditDefaultsOnly, Category = Montages)
UAnimMontage* EquipMontage;

播放函数很简单,只需要判断实例存在,传入sectionname。

void ACharacter01::PlayEquipMontage(FName SectionName)
{
	// 获取角色的骨架并检查是否存在动画实例以及蒙太奇(Montage)
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	if (AnimInstance && EquipMontage)
	{	// 在动画实例上播放蒙太奇
		AnimInstance->Montage_Play(EquipMontage);
		// 跳转到所选的攻击部分
		AnimInstance->Montage_JumpToSection(SectionName, EquipMontage);
	}
}

回到按键E的函数,简单修改,这是还应该添加一个武器状态,看他是不是被我们拿起来。这样才能装备和卸下,在重叠拿起时把这个变量设置重叠物,最后在人物蓝图里吧equipmontage设置为我们的装备蒙太奇。

void ACharacter01::EKeyPressed()
{	//当重叠的物体为武器类获取改物体
	AWeapon* OverlappingWeapon = Cast<AWeapon>(OverlappingItem);
	if (OverlappingWeapon)
	{
		OverlappingWeapon->Equip(GetMesh(),FName("RightHandSocket"));
		CharacterState = ECharacterState::ECS_EquipedOneHandWeapon;
	}
	else
	{	//收起武器,并设置人物转态
		if(CanDisarm())
		{
			PlayEquipMontage(FName("Unequip"));
			CharacterState = ECharacterState::ECS_Unequiped;
		}
		//拿出武器
		else if (Canarm())
		{
			PlayEquipMontage(FName("Equip"));
			CharacterState = ECharacterState::ECS_EquipedOneHandWeapon;
		}
	
	}
}

完成后发现装备武器后还会卸下武器,排查后发现是蒙太奇里边没有断开动画连续播放了

让剑粘在背部

和放在手上一样,我们需要在背部也上一个socket,在spine05插入一个socket,插入剑的模型调整位置,差不多就行。在蒙太奇里边插入一个武器脱离手的通知notify。

将这段函数的上两句选中右键重构,可以拿出一个附加到socket的函数,会自动为我们创建函数并替换

void AWeapon::Equip(USceneComponent* InParent, FName InSocketName)
{	
	// 创建一个 FAttachmentTransformRules 对象,规定附着的规则。
	FAttachmentTransformRules TransformRules(EAttachmentRule::SnapToTarget, true);
	// 将武器的 ItemMesh 附着到InParent的 Mesh 上,并使用Socket作为附着点
	ItemMesh->AttachToComponent(InParent, TransformRules, InSocketName);
	ItemState = EItemState::EIS_OnHand;
}
void AWeapon::AttachMeshToSocket(USceneComponent* InParent, const FName& InSocketName)
{
	// 创建一个 FAttachmentTransformRules 对象,规定附着的规则。
	FAttachmentTransformRules TransformRules(EAttachmentRule::SnapToTarget, true);
	// 将武器的 ItemMesh 附着到InParent的 Mesh 上,并使用Socket作为附着点
	ItemMesh->AttachToComponent(InParent, TransformRules, InSocketName);
}

现在我们需要一个蓝图可读的函数来让notify执行Disarm函数(在人物cpp里)这样我们就可以把剑放在背部,拿起剑也一样

void ACharacter01::Disarm()
{
	if (EquippedWeapon)
	{
		EquippedWeapon->AttachMeshToSocket(GetMesh(),FName("SpineSocket"));
	}
}

此时我们在移动的时候还能收剑,想要取消。添加一个动作状态正在装备就可以,同时还需要在动画结束时在添加一个notify来重置ActionState状态为未被占用

在移动里修改判断条件

装备武器的音效

使用metasound制作一个音效,然后使用代码来播放,对于不同的武器使用不同的声音。在武器头文件新建一个变量

// 武器装备时播放的音效
UPROPERTY(EditAnywhere, Category = "Weapon Properties")
USoundBase* EquipSound;


void AWeapon::Equip(USceneComponent* InParent, FName InSocketName)
{
	// 调用 AttachMeshToSocket 函数将武器的 Mesh 附加到指定的骨骼插槽上
	AttachMeshToSocket(InParent, InSocketName);

	// 设置武器的状态为在手上
	ItemState = EItemState::EIS_OnHand;

	// 如果设置了装备音效,就在武器的位置播放音效
	if (EquipSound)
	{
		UGameplayStatics::PlaySoundAtLocation(this, EquipSound, GetActorLocation());
	}
}

然后进入剑的蓝图为它设置单独的音效

此时装备武器后还按e还会发出声音,因为两个胶囊体一直在重叠,因此我们要在拿起武器后关闭它的重叠,在上边的代码里在加上下边这一行

if (Sphere)
{
	Sphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

优化动画

在调试的过程中可以an“~”输入slomo 0.1,这样所有的东西都会按0.1秒来播放方便看,在动画蓝图总可以使用key来修改部分动画而不会影响整体。

首先找到要修改的开始和结尾,选定骨骼节点分别创建一个key,然后在中间位置调整骨骼节点的位置在添加一个就完成了

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

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

相关文章

【多样注释】刚入职就崩溃!这段神秘注释让人无法忍受

最近写码写的头晕脑涨&#xff0c;同事听完后给我发来几张神图&#xff0c;我看完当场笑尿&#x1f923;&#xff0c;分享一下&#xff0c;权当博君一笑了。 代码注释图案传送门 1、看到了这个注释&#xff0c;心凉了一半 2、阅读源码的人&#xff0c;心里一定的崩溃的 3、这…

SwiftUI - 界面布局知识点

前言 SwiftUI采用的布局方式是和Flutter一样是弹性布局&#xff0c;而不是iOS之前的坐标轴的方式布局&#xff0c;不用准确的设置出位置大小&#xff0c;只需要设置当前视图大小及视图间排布的方式。灵活性增强&#xff0c;布局操作简便&#xff0c;SwiftUI与Flutter布局原理一…

Flowable串行流程移动活动

在Activiti6和Activiti7中跳转节点都要自己实现&#xff0c;Flowable增加了这个功能。 一&#xff1a;简介 串行流程是指简单的一条线的流程&#xff0c;流程中如果包含会签、排它网关也算串行流程。 节点移动有三种方式&#xff1a; 向前移动foreward。向后移动back。直接跳…

一文看懂香港优才计划和高才通计划的区别和优势?如何选?

一文看懂香港优才计划和高才通计划的区别和优势&#xff1f;如何选&#xff1f; 为什么很多人都渴望有个香港身份&#xff1f; 英文这里和内地文化相近&#xff0c;语言相通&#xff0c;同时税率较低、没有外汇管制&#xff0c;有稳定金融体制和良好的营商环境&#xff0c;诸多…

java入门, 记录检测网络

一、需求 在开发中&#xff0c;我们经常需要本地连接服务器&#xff0c;或者数据库这些机器或者组件&#xff0c;但是有时候网络不通&#xff0c;我们怎样检测&#xff0c;除了ping 和 telnet 还需要那些常用的技能。 二、检测网络 1、一般我们先ping一些需要连接的网络ip 或…

WY-35A4三相欠压继电器 导轨安装,延时动作0-99.99s可调

系列型号 单相 JY-45A1电压继电器&#xff1b;JY-45B1电压继电器&#xff1b; JY-45C1电压继电器&#xff1b;JY-45D1电压继电器&#xff1b; JY-41A1电压继电器&#xff1b;JY-41B1电压继电器&#xff1b; JY-41C1电压继电器&#xff1b;JY-41D1电压继电器&#xff1b; …

企业数字化建设之——老板关注的IT指标有哪些 ?

投资回报ROI | 商业价值 | 系统可用性 | 业务的参与程度 | 技术债务指数 降本&#xff0c;增效是IT部门工作的永恒话题 &#xff0c;降低成本 &#xff0c;增加效益 &#xff0c;降本增效的工作方向&#xff1a; 1 年初KPI目标、目标完成情况、关键证据、公司主线工作…

主流接口测试框架对比

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

基于SSM的供电所档案管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

前端入门(二)js速成与vue脚手架搭建

文章目录 JS常用API操作对象操作对象增删改查js深拷贝、浅拷贝js实现深拷贝的方式 安全访问 JS常用API操作 对象操作 对象增删改查 创建对象 let obj {}新增属性 obj.a 1 、obj[a] 1修改属性 obj.a ‘a’查询属性 obj.a 、obj[a]删除属性 delete obj.a js深拷贝、浅拷贝…

【无线网络技术】——无线传输技术基础(学习笔记)

目录 &#x1f552; 1. 无线传输媒体&#x1f558; 1.1 地面微波&#x1f558; 1.2 卫星微波&#x1f558; 1.3 广播无线电波&#x1f558; 1.4 红外线&#x1f558; 1.5 光波 &#x1f552; 2. 天线&#x1f558; 2.1 辐射模式&#x1f558; 2.2 天线类型&#x1f564; 2.2.1 …

Power Automate-与Microsoft Forms连接

创建自动化云端流&#xff0c;流的触发器选择第一个提交新回复时 点击蓝色的Change connection&#xff0c;登录创建Microsoft Forms表单的账号 选择提前创建的表单&#xff1b;如果想连接其他账号创建的Microsoft Forms表单&#xff0c;可以再次点击蓝色的Change connection&a…

RT-DETR算法优化改进:Backbone改进|RIFormer:无需TokenMixer也能达成SOTA性能的极简ViT架构 | CVPR2023

💡💡💡本文独家改进:RIFormer助力RT-DETR ,替换backbone, RIFormer-M36的吞吐量可达1185,同时精度高达82.6%;而PoolFormer-M36的吞吐量为109,精度为82.1%。 推荐指数:五星 RT-DETR魔术师专栏介绍: https://blog.csdn.net/m0_63774211/category_12497375.html …

SPL机制与使用,组件化技术核心点打法

什么是SPI SPI &#xff0c;全称为 Service Provider Interface&#xff0c;是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件&#xff0c;自动加载文件里所定义的类。 SPI 的本质是将接口实现类的全限定名配置在文件中&#xff0c;并由服务加…

springboot项目的可执行jar以后台本地服务的方式运行在Windows机器上

文章目录 先上一个效果图准备可执行文件注册及启动服务用到的工具 前段时间遇到一个项目&#xff0c;需要我们提供一个驱动控件&#xff0c;可以以后台服务的方式运行在Windows机器上。开始寻找各种解决办法。 最后发现一个不错的解决方式。分享给大家一下。 先上一个效果图 准…

vue2项目从0搭建(一):项目搭建

前言: vue2项目可谓十分常见,国内大部分的前端码农应该都是用vue2技术在开发,虽然vue3和react等技术也有很多,但是占据绝大多数的中高级搬砖码农应该干的都是vue2技术的项目,就算现在很多人转战vue3技术了,但是维护原有vue2的项目应该也是很多的。 我本来是不打算写vue2的技术…

用Go实现yaml文件节点动态解析

1.摘要 在大多数Go语言项目中, 配置文件通常为yaml文件格式, 在文件中可以设置项目中可灵活配置的各类参数, 通常这类参数都是比较固定的, 可以将其映射为对应的结构体在项目中进行使用, 如果需要调整参数时, 只需要增减结构体参数字段内容即可。 但同时还存在另外一种情况, …

文献阅读——Layered Costmaps for Context-Sensitive Navigation

摘要 许多导航系统&#xff0c;包括无处不在的ROS导航堆栈&#xff0c;在单个成本图上执行路径规划&#xff0c;其中大部分信息存储在单个网格中。这种方法在生成最小长度的无碰撞路径方面非常成功&#xff0c;但是当成本图中的值超出已占用或空闲空间时&#xff0c;它在动态的…

ATFX汇市:美国10月CPI数据来袭,通胀率料将进一步走低

ATFX汇市&#xff1a;本周二21:30&#xff0c;美国劳工部将公布10月未季调CPI年率&#xff0c;前值为3.7%&#xff0c;预期值3.3%&#xff1b;9月未季调核心CPI年率将于同一时间公布&#xff0c;前值为4.1%&#xff0c;预期值4.1%。机构预期美国名义通胀率将显著下降&#xff0…

EasyA正在帮助Sui为新一代Web3 App培养构建者

最近&#xff0c;我们采访了Phil和Dom Kwok&#xff0c;他们是兄弟也是Web3教育移动应用EasyA的共同创始人。这个教育app通过学习模块和编码挑战的形式&#xff0c;向开发人员教授有关不同区块链及其独特特性的知识。他们在十月初推出了他们的第一个Sui模块&#xff0c;并在随后…