IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> UE4学习监督——C++人物攻击(二) -> 正文阅读

[游戏开发]UE4学习监督——C++人物攻击(二)

上一章我们初步完成了攻击功能的实现,但是会出现滑步现象,且攻击方式过于单一,这次我们来解决这个问题。

此时我们需要重写动画蓝图类。

创建一个类继承自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<ACharacter>(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<UAnimInstance>(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<UAnimInstance>(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语句判断不同的攻击状态,分支中设置定时器运行时间,在下一个分支语句中清除之前设置的定时器,之后重新设置。

编译运行,已能完成既定目标。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-11-09 19:56:40  更:2021-11-09 19:57:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 0:42:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码