二十一、完成玩家动画蓝图
添加数据类型
//上半身动画的状态
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
查看骨骼融合是否设置骨骼