斯坦福UE4 + C++课学习记录 8:添加攻击动画

一、添加动画

  1. 实现右手发射魔法粒子的动画
  2. 动画序列Animation Sequence:是预先录制的一系列骨骼动画帧,可以应用于骨骼网格体Skeletal Mesh上。它们通常由动画师在3D建模软件(如MayaBlender)中创建后导入到UE中。通常是FBX格式。在游戏中,通过调用相应的函数播放动画序列。
  • 一个动画序列包含许多个关键帧,这些关键帧规定了骨骼网格体中骨骼在特定时间点位置旋转缩放信息。通过按照顺序混合这些关键帧,就能在骨骼网格体上播放骨骼动画了。
  • 应用方式?
    (1)角色蓝图:在角色蓝图中,通过动画蓝图Animation Blueprint设置动画序列。
    (2)动画蓝图:在动画蓝图中使用状态机State Machine动画图Anim Graph将动画序列连接到角色的骨骼网格体。
  1. 蒙太奇Montage :是更为复杂和灵活的动画资产,允许将多个 动画序列动画片段Animation Clips组合在一起,并在特定时间点插入动画事件Animation Events或执行动画通知Anim Notifies。是控制动画播放的系统。
  • 还可以使用动画蒙太奇来在网络游戏中复制根位移Root Motion 动画。
  • 可以切分为多个蒙太奇分段Montage Sections,以便在运行时,按一定逻辑以任何顺序动态播放。
  • 在蒙太奇编辑器中,可以使用不同的轨道Tracks段落Sections来组织和控制动画片段。可以添加动画通知来触发特定事件(如声音效果、粒子效果等)。
  • 通过角色蓝图动画蓝图中的Montage_Play函数来播放蒙太奇。

动画序列和蒙太奇的区别
(1)复杂度:动画序列比较简单,适用于播放单一的动画动作;蒙太奇更复杂,适用于组合和管理多个动画动作。
(2)灵活性:蒙太奇允许在特定时间点插入动画通知和事件,提供了更高的灵活性和控制力。
(3)用途:动画序列适用于基本的循环动画(如行走、跑步等),而蒙太奇适用于复杂的动画行为(如连招、攻击组合等)。

  1. 在SCharacter.cpp的PrimaryAttack函数实现播放动画的功能。
  2. 在使用UPROPERTY宏时加上Category,可以使相关的变量在蓝图编辑器中显示在指定类别下。
// SurCharacter.cpp -> PrimaryAttack()
PlayAnimMontage(AttackAnim);

// SurCharacter.h
// Category指定在蓝图编辑工具中显示时的属性类别
UPROPERTY(EditAnywhere, Category = "Attack")
UAnimMontage* AttackAnim;

// 之前的投射体子类,也加上Category
UPROPERTY(EditAnywhere, Category = "Attack")
SubclassOf<AActor> ProjectileClass;
  1. 在UE中给AttackAnim选择动画
  2. 此时魔法粒子发射的位置还是之前写的角色在静止状态下右手的位置,而没有从角色抬手后的手掌中发出来。之前的计算位置:
 FVector RightHandLoc = GetMesh()->GetSocketLocation("Muzzle_01"); 
  • 解决方法:根据动画的速度在这条语句前设置相应延迟即可,也就是等0.2秒的抬手时间后,再生成粒子。所以我们利用UE中的计时器来实现这个效果
// 左键攻击
void ASurCharacter::PrimaryAttack() {

	PlayAnimMontage(AttackAnim);
    // 0.2s延迟后触发魔法粒子生成
	GetWorldTimerManager().SetTimer(TimerHandle_PrimaryAttack, this, &ASurCharacter::PrimaryAttack_TimeElapsed, 0.18f);

}
// 原先控制魔法粒子的内容移到这个函数中
void ASurCharacter::PrimaryAttack_TimeElapsed() {
	// 获取模型右手位置
	FVector RightHandLoc = GetMesh()->GetSocketLocation("Muzzle_01");

	// 朝向角色方向,在角色的右手位置生成
	FTransform SpawnTM = FTransform(GetActorRotation(), RightHandLoc);

	// 此处设置碰撞检测规则为:即使碰撞也总是生成
	FActorSpawnParameters SpawnParams;
	SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

	GetWorld()->SpawnActor<AActor>(ProjectileClass, SpawnTM, SpawnParams);
} 
  • 定时器句柄 TimerHandle_PrimaryAttack是FTimerHandle类,需要在SCharacter.h文件中声明。只要定时器句柄存在,过0.2s后就会执行PrimaryAttack_TimeElapsed()中发射粒子的代码。这样做的好处是:当角色在攻击的一瞬间死亡时,其TimerHandle_PrimaryAttack将会自动取消,那之后的动画也就不会再播放。
  1. 定时器句柄:是一个用来标识和管理特定定时器的对象。它允许来设置定时器、查询定时器状态、以及取消定时器。

(1)创建定时器:使用FTimerHandleGetWorld()->GetTimerManager()来设置定时器。SetTimer函数是主要的接口,它允许设置定时器的间隔时间回调函数是否循环等。

FTimerHandle TimerHandle;
GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &AMyClass::MyFunction, 5.0f, false);

(2)取消定时器:

GetWorld()->GetTimerManager().ClearTimer(TimerHandle);

(3)检查定时器是否有效:

bool bIsTimerActive = GetWorld()->GetTimerManager().IsTimerActive(TimerHandle);

(4)重置定时器

GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &AMyClass::MyFunction, 5.0f, false);
  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值