上一章我们初步完成了攻击功能的实现,但是会出现滑步现象,且攻击方式过于单一,这次我们来解决这个问题。
此时我们需要重写动画蓝图类。
创建一个类继承自AnimInstance,命名为HeroAnimInstance。
头文件如下
class DDEMO_API UHeroAnimInstance : public UAnimInstance { GENERATED_BODY() public: UPROPERTY(BlueprintReadOnly) float Speed; UPROPERTY(BlueprintReadOnly) float Direction; UPROPERTY(BlueprintReadOnly) bool bInAir; UPROPERTY(BlueprintReadOnly) bool isAttack; UPROPERTY(EditAnywhere,BlueprintReadOnly) class AHeroDemo* Hero; UFUNCTION(BlueprintCallable) void UpdateAnimInfo(float dt); };
cpp文件如下
void UHeroAnimInstance::UpdateAnimInfo(float dt) { APawn* Owner = TryGetPawnOwner(); ACharacter* Player = Cast(Owner); if(Owner!=nullptr) { Speed = Owner->GetVelocity().Size(); Direction = CalculateDirection(Owner->GetVelocity(), Owner->GetbaseAimRotation()); bInAir = Player->GetMovementComponent()->IsFalling(); } }
完成后进行编译,并以此为父类创建动画蓝图。蓝图内的 *** 作基本与之前一致。
现在修改HeroDemo的代码。
在头文件增加如下代码:
bool bAttacking;//为判断是否在攻击 UFUNCTION(BlueprintCallable)//判定攻击动画结束,需要在动画蓝图中调用 void AttackEnd();
将头文件中移动的函数做一些修改,使之在攻击时不能调用。如:
void AHeroDemo::MoveForward(float Axis) { if((Controller!=NULL)&(Axis!=0.0f) #if 1 &&!bAttacking #endif //以上代码用来作一个判断 ){ const FRotator Rotation = Controller->GetControlRotation(); const FRotator YawRotation(0, Rotation.Yaw, 0); const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); AddMovementInput(Direction, Axis); } }
Attack()更改如下:
void AHeroDemo::Attack() { bAttacking = true; UAnimInstance* AnimInstance = Cast(GetMesh()->GetAnimInstance()); if (AnimInstance != nullptr) { if (!AnimInstance->Montage_IsPlaying(AttackMontage)) { AnimInstance->Montage_Play(AttackMontage); AnimInstance->Montage_JumpToSection(FName("Attack01"), AttackMontage); } } }
AttackEnd()代码如下:
void AHeroDemo::AttackEnd() { bAttacking = false; }
但是我们的代码中却没有调用AttackEnd函数,我们需要到动画蓝图中调用,通过获得蒙太奇动画的结束时间来判断何时调用。
来到AttackM动画蒙太奇,添加两段攻击动画,并将三段动画在分段中命名为Attack01,Attack02,Attack03,并进行分段,效果如下:
再在下方通知中创建新通知,命名为AttackEnd,将位置调整到第一段攻击动画结束处。再分别复制两次到另外两段攻击动画。
这样,当蒙太奇动画播放完成时就会发出通知。
再来到动画蓝图的事件图表,调用并连接节点如下:
编译运行,发现在攻击时方向键已然失效。
现在我们来设置不同的攻击状态,期望的目标是连续点击左键有三种不同的攻击动画,如连续两次点击之间时间间隔超过5s则重新计算。
增加的代码如下。
.h
int AttackStatus = 1; //用于判断攻击状态 FTimerHandle RestTimer; //声明定时器 void ClearRestTime(); //清除之前的攻击状态
.cpp
void AHeroDemo::ClearRestTime() { AttackStatus = 1; }
更改.cpp中Attack函数如下:
void AHeroDemo::Attack() { bAttacking = true; UAnimInstance* AnimInstance = Cast(GetMesh()->GetAnimInstance()); if (AnimInstance != nullptr) { if (!AnimInstance->Montage_IsPlaying(AttackMontage)) { AnimInstance->Montage_Play(AttackMontage); switch (AttackStatus) { case 1:AnimInstance->Montage_JumpToSection(FName("Attack01"), AttackMontage); AttackStatus++; GetWorldTimerManager().SetTimer(RestTimer, this, &AHeroDemo::ClearRestTime, 0.1f, false, 3.0f); break; case 2:AnimInstance->Montage_JumpToSection(FName("Attack02"), AttackMontage); AttackStatus++; GetWorldTimerManager().ClearTimer(RestTimer); GetWorldTimerManager().SetTimer(RestTimer, this, &AHeroDemo::ClearRestTime, 0.1f, false, 3.0f); break; case 3:AnimInstance->Montage_JumpToSection(FName("Attack03"), AttackMontage); GetWorldTimerManager().ClearTimer(RestTimer); AttackStatus = 1; break; } } } }
这里使用switch语句判断不同的攻击状态,分支中设置定时器运行时间,在下一个分支语句中清除之前设置的定时器,之后重新设置。
编译运行,已能完成既定目标。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)