二十一、完成玩家动画蓝图

添加数据类型

//上半身动画的状态
namespace EUpperBody
{
    
    
	enum Type
	{
    
    
		None = 0,
		Punch,
		Hit,
		Fight,
		PickUp,
		Eat
	};
}

编辑一、三人称动画蓝图

按下图设置
在这里插入图片描述

点击鼠标左右键播放Montage

项目设置中添加Action LeftEvent和RightEvent
左右手预动作赋值

鼠标事件与预动作

//按钮事件
private:
	void LeftEventStart();
	void LeftEventStop();
	void RightEventStart();
	void RightEventStop();
	
private:

	//左键预动作
	EUpperBody::Type LeftUpperType;

	//右键预动作
	EUpperBody::Type RightUpperType;

// Fill out your copyright notice in the Description page of Project Settings.

#include "SlAiPlayerController.h"
#include "Player/SlAiPlayerCharacter.h"
...
void ASlAiPlayerController::SetupInputComponent()
{
    
    
...
	//绑定鼠标按下事件
	InputComponent->BindAction("LeftEvent", IE_Pressed, this, &ASlAiPlayerController::LeftEventStart);
	InputComponent->BindAction("LeftEvent", IE_Released, this, &ASlAiPlayerController::LeftEventStop);
	InputComponent->BindAction("RightEvent", IE_Pressed, this, &ASlAiPlayerController::RightEventStart);
	InputComponent->BindAction("RightEvent", IE_Released, this, &ASlAiPlayerController::RightEventStop);
}

void ASlAiPlayerController::BeginPlay()
{
    
    
...
	//设置预动作
	LeftUpperType = EUpperBody::Punch;
	RightUpperType = EUpperBody::PickUp;
	
}



void ASlAiPlayerController::ChangeView()
{
    
    
	
	//如果不允许切换视角,直接返回
	if (!SPCharacter->IsAllowSwitch) return;

	switch (SPCharacter->GameView)
	{
    
    
	case EGameViewMode::Third:
		SPCharacter->ChangeView(EGameViewMode::First);
		break;
	case EGameViewMode::First:
		SPCharacter->ChangeView(EGameViewMode::Third);
		break;
	}
	
}
//鼠标事件对应播放的Montage

void ASlAiPlayerController::LeftEventStart()
{
    
    
	SPCharacter->UpperType = LeftUpperType;
}

void ASlAiPlayerController::LeftEventStop()
{
    
    
	SPCharacter->UpperType = EUpperBody::None;
}

void ASlAiPlayerController::RightEventStart()
{
    
    
	SPCharacter->UpperType = RightUpperType;
}

void ASlAiPlayerController::RightEventStop()
{
    
    
	SPCharacter->UpperType = EUpperBody::None;
}

更新动画状态

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "SlAiTypes.h"
#include "SlAiPlayerAnim.generated.h"

/**
 * 
 */
UCLASS()
class SLAICOURSE_API USlAiPlayerAnim : public UAnimInstance
{
    
    
	GENERATED_BODY()
	

public:

	USlAiPlayerAnim();

	virtual void NativeUpdateAnimation(float DeltaSeconds) override;
	
public:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = PlayAnim)
		float Speed;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = PlayAnim)
		FRotator SpineRotator;

protected:

	//获取角色指针
	void InitSPCharacter();

	//更新属性
	virtual void UpdateParameter();

	//更新动作
	virtual void UpdateMontage();

	//修改是否允许切换视角
	void AllowViewChange(bool IsAllow);

protected:

	//角色指针
	class ASlAiPlayerCharacter* SPCharacter;

	//上半身的Montage
	class UAnimMontage* PlayerHitMontage;
	UAnimMontage* PlayerEatMontage;
	UAnimMontage* PlayerFightMontage;
	UAnimMontage* PlayerPunchMontage;
	UAnimMontage* PlayerPickUpMontage;

	//保存当前播放的Montage
	UAnimMontage* CurrentMontage;

	//指定自己的运行人称
	EGameViewMode::Type GameView;
//第三人称 GameView = EGameViewMode::Third;
//第一人称 GameView = EGameViewMode::First;
};
// Fill out your copyright notice in the Description page of Project Settings.

#include "SlAiPlayerAnim.h"
#include "Player/SlAiPlayerCharacter.h"
#include "Animation/AnimMontage.h"

USlAiPlayerAnim::USlAiPlayerAnim()
{
    
    
	Speed = 0.f;
	SpineRotator = FRotator(0.f, 0.f, 0.f);
}

void USlAiPlayerAnim::NativeUpdateAnimation(float DeltaSeconds)
{
    
    
	//初始化角色指针
	InitSPCharacter();
	//更新蓝图数据
	UpdateParameter();
	//更新蒙太奇
	UpdateMontage();
}

void USlAiPlayerAnim::InitSPCharacter()
{
    
    
	if (!SPCharacter)
		SPCharacter = Cast<ASlAiPlayerCharacter>(TryGetPawnOwner());
}

void USlAiPlayerAnim::UpdateParameter()
{
    
    
	//如果不存在直接返回,避免空指针产生中断
	if (!SPCharacter) return;
	//设置速度
	Speed = SPCharacter->GetVelocity().Size();
	//定义上半身的旋转
	float SpineDir = SPCharacter->GetActorRotation().Yaw - 90.f;
	if (SpineDir > 180.f) SpineDir -= 360.f;
	if (SpineDir < -180.f) SpineDir += 360.f;
	SpineRotator = FRotator(0.f, SpineDir, 90.f);
}


void USlAiPlayerAnim::UpdateMontage()
{
    
    
	//如果不存在直接返回,避免空指针产生中断
	if (!SPCharacter) return;

	//如果当前的人称状态和这个动作的不一致,直接返回
	if (SPCharacter->GameView != GameView) return;

	//如果当前的动作没有停止,不更新动作
	if (!Montage_GetIsStopped(CurrentMontage)) return;

	switch (SPCharacter->UpperType)
	{
    
    
	case EUpperBody::None:
		//如果有哪个动作在播放
		if (CurrentMontage != nullptr)
		{
    
    
			Montage_Stop(0);
			CurrentMontage = nullptr;
			//允许切换视角
			AllowViewChange(true);
		}
		break;
	case EUpperBody::Punch:
		if (!Montage_IsPlaying(PlayerPunchMontage))
		{
    
    
			Montage_Play(PlayerPunchMontage);
			CurrentMontage = PlayerPunchMontage;
			//不允许切换视角
			AllowViewChange(false);
		}
		break;
	case EUpperBody::Hit:
		if (!Montage_IsPlaying(PlayerEatMontage))
		{
    
    
			Montage_Play(PlayerEatMontage);
			CurrentMontage = PlayerEatMontage;
			AllowViewChange(false);
		}
		break;
	case EUpperBody::Fight:
		if (!Montage_IsPlaying(PlayerFightMontage))
		{
    
    
			Montage_Play(PlayerFightMontage);
			CurrentMontage = PlayerFightMontage;
			AllowViewChange(false);
		}
		break;
	case EUpperBody::PickUp:
		if (!Montage_IsPlaying(PlayerPickUpMontage))
		{
    
    
			Montage_Play(PlayerPickUpMontage);
			CurrentMontage = PlayerPickUpMontage;
			AllowViewChange(false);
		}
		break;
	case EUpperBody::Eat:
		if (!Montage_IsPlaying(PlayerEatMontage))
		{
    
    
			Montage_Play(PlayerEatMontage);
			CurrentMontage = PlayerEatMontage;
			AllowViewChange(false);
		}
		break;
	}
}


void USlAiPlayerAnim::AllowViewChange(bool IsAllow)
{
    
    
	if (!SPCharacter) return;
	SPCharacter->IsAllowSwitch = IsAllow;
}

调整骨骼角度

按下图设置
在这里插入图片描述

过一遍

点击左键
按下
调用

void ASlAiPlayerController::LeftEventStart()
{
    
    
	SPCharacter->UpperType = LeftUpperType;
}
//设置预动作
	LeftUpperType = EUpperBody::Punch;

动画更新

void USlAiPlayerAnim::NativeUpdateAnimation(float DeltaSeconds)
{
    
    
	//初始化角色指针
	InitSPCharacter();
	//更新蓝图数据
	UpdateParameter();
	//更新蒙太奇
	UpdateMontage();
}

抬起
调用

void ASlAiPlayerController::LeftEventStop()
{
    
    
	SPCharacter->UpperType = EUpperBody::None;
}

动画更新

void USlAiPlayerAnim::NativeUpdateAnimation(float DeltaSeconds)
{
    
    
	//初始化角色指针
	InitSPCharacter();
	//更新蓝图数据
	UpdateParameter();
	//更新蒙太奇
	UpdateMontage();
}

注意

如果切换到第一人称点击左键却播放不出Montage
查看骨骼融合是否设置骨骼
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_51032168/article/details/121526054