角色移动与视角控制
Character类与相关API
- 创建Character子类
- MainPlayer.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MainPlayer.generated.h"
UCLASS()
class UEGAME_API AMainPlayer : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMainPlayer();
//新建一个SpringArm
UPROPERTY(visibleAnywhere,BlueprintReadOnly)
class USpringArmComponent* SpringArm;
//新建一个Camera
UPROPERTY(visibleAnywhere, BlueprintReadOnly)
class UCameraComponent* FollowCamera;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
- MianPlayer.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
// Sets default values
AMainPlayer::AMainPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
//设置SPringArm无碰撞臂长
SpringArm->TargetArmLength = 600.f;
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(SpringArm, NAME_None);
}
// Called when the game starts or when spawned
void AMainPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMainPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMainPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
- 运行结果
指定骨骼模型并调整胶囊体
- 指定骨骼模型
-
C++硬编码给出默认值
-
头文件胶囊体#include "Components/CapsuleComponent.h"
cpp
//设置胶囊体的默认宽高
GetCapsuleComponent()->SetCapsuleSize(35.f, 100.f);
创建轴映射与GameMode
- 创建关卡GameMode子类
- 设置玩家使用默认类
- 轴映射
基本简单移动与旋转控制
- AddMovementInput:沿着给定的世界方向向量(通常是标准化的)添加移动输入,并按"ScaleValue"进行缩放。如果ScaleValue < 0,则移动方向相反。基础Pawn类不会自动应用移动,这取决于用户在Tick事件中这样做。像Character和DefaultPawn这样的子类会自动处理这些输入并移动。
-
GetActorForwardVector:获取Actor,X轴正向的向量
-
GetActorRightVector:获取Actor,Y轴正向的向量
MainPlayer.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
// Sets default values
AMainPlayer::AMainPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
//设置SPringArm无碰撞臂长
SpringArm->TargetArmLength = 600.f;
SpringArm->bUsePawnControlRotation = true;//硬编码SpringArm继承controlller旋转为真
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(SpringArm, NAME_None);
FollowCamera->bUsePawnControlRotation = false;//硬编码FollowCamera继承controlller旋转为假
//设置胶囊体的默认宽高
GetCapsuleComponent()->SetCapsuleSize(35.f, 100.f);
}
// Called when the game starts or when spawned
void AMainPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMainPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMainPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//检查PlayerInputComponent指针,check函数只能在这使用
check(PlayerInputComponent);
//绑定轴映射事件
PlayerInputComponent->BindAxis("MoveForward", this, &AMainPlayer::MoveForward);
PlayerInputComponent->BindAxis("MoveRigth", this, &AMainPlayer::MoveRigth);
//绑定Controller控制器去管理视角旋转
PlayerInputComponent->BindAxis("Turn", this, &ACharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &ACharacter::AddControllerPitchInput);
}
void AMainPlayer::MoveForward(float value)
{
//沿着给定的世界方向向量(通常是标准化的)添加移动输入
AddMovementInput(GetActorForwardVector(), value);
}
void AMainPlayer::MoveRigth(float value)
{
AddMovementInput(GetActorRightVector(), value);
}
控制角色旋转
- 相机的选择和角色的旋转应该是两个独立的事件
- 我们需要分离控制相机的鼠标控制旋转(ControlRotation)和角色旋转(Pawn Rotation)。
- 在UE中XYZ轴的正向分别对应前方、右方和上方,显示的箭头颜色分别为红色、绿色和蓝色(三基色的习惯顺序)。
- 头文件 #include "GameFramework/PlayerController.h"
- Controller:这是Character类中自己声明的AController* 属性,用与获取该Actor的控制器
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/PlayerController.h"
// Sets default values
AMainPlayer::AMainPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
//设置SPringArm无碰撞臂长
SpringArm->TargetArmLength = 600.f;
SpringArm->bUsePawnControlRotation = true;//硬编码SpringArm继承controlller旋转为真
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(SpringArm, NAME_None);
FollowCamera->bUsePawnControlRotation = false;//硬编码FollowCamera继承controlller旋转为假
//设置胶囊体的默认宽高
GetCapsuleComponent()->SetCapsuleSize(35.f, 100.f);
//对Character的Pawn进行硬编码
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
}
// Called when the game starts or when spawned
void AMainPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMainPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMainPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//检查PlayerInputComponent指针,check函数只能在这使用
check(PlayerInputComponent);
//绑定轴映射事件
PlayerInputComponent->BindAxis("MoveForward", this, &AMainPlayer::MoveForward);
PlayerInputComponent->BindAxis("MoveRigth", this, &AMainPlayer::MoveRigth);
//绑定Controller控制器去管理视角旋转
PlayerInputComponent->BindAxis("Turn", this, &ACharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &ACharacter::AddControllerPitchInput);
}
void AMainPlayer::MoveForward(float value)
{
//获取到Control旋转
FRotator Rotation = Controller->GetControlRotation();
//转向只关注水平Yaw方向,因此置0防止影响
FRotator YowRotation = FRotator(0.0f, Rotation.Yaw, 0.0f);
//获取相机(鼠标控制器的朝向),并且朝这个轴的方向移动
FVector Direction = FRotationMatrix(YowRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, value);
}
void AMainPlayer::MoveRigth(float value)
{
//获取到Controller旋转
FRotator Rotation = Controller->GetControlRotation();
//转向只关注水平Yaw方向,因此置0防止影响
FRotator YowRotation = FRotator(0.0f, Rotation.Yaw, 0.0f);
//获取相机(鼠标控制器的朝向),并且朝这个轴的方向移动
FVector Direction = FRotationMatrix(YowRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(Direction, value);
}
使角色自动面向移动方向
- CharacterMovement非常强大,我们打开CharacterMovement的Orient Rotation to Movement就开启自动面向旋转
- 头文件:#include "GameFramework/CharacterMovementComponent.h"
cpp
//硬编码orient Rotation to Movement,给个默认转向速率
GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f);
- 运行结果
创建键盘与手柄使用的视角与旋转函数
- 新建两个float变量来控制上下左右转向的速率,注意旋转时要乘以DeltaTime避免高低性能差值
cpp
float BaseTurnRate; //使用键盘X转向的速率
float BaseLookUpRate; //使用键盘Y转向的速率
//给键盘控制转向的速率变量赋初值
BaseTurnRate = 21.f;
BaseLookUpRate = 21.f;
- 因为可能要修改视角限制,新建Turn与LookUp绑定Controller控制器去管理视角旋转函数,新建绑定键盘鼠标轴映射事件函数
cpp
private:
void MoveForward(float value);
void MoveRight(float value);
void Turn(float Value);
void LookUp(float Value);
void TurnRate(float Rate);
void LookUpRate(float Rate);
cpp
// Called to bind functionality to input
void AMainPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//检查PlayerInputComponent指针,check函数只能在这使用
check(PlayerInputComponent);
//绑定移动轴映射事件
PlayerInputComponent->BindAxis("MoveForward", this, &AMainPlayer::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AMainPlayer::MoveRight);
//绑定Controller控制器去管理视角旋转
PlayerInputComponent->BindAxis("Turn", this, &AMainPlayer::Turn);
PlayerInputComponent->BindAxis("LookUp", this, &AMainPlayer::LookUp);
//绑定键盘鼠标轴映射事件
PlayerInputComponent->BindAxis("TurnRate", this, &AMainPlayer::TurnRate);
PlayerInputComponent->BindAxis("LookUpRate", this, &AMainPlayer::LookUpRate);
}
cpp
void AMainPlayer::Turn(float Value)
{
if (Value != 0.f)
{
AddControllerYawInput(Value);
}
}
void AMainPlayer::LookUp(float Value)
{
if (Value != 0.f)
{
AddControllerPitchInput(Value);
}
}
void AMainPlayer::TurnRate(float Rate)
{
//要乘以一个DeltaTime这样就可以避免高帧底帧差值问题
float Value = Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds();
if (Value != 0.f)
{
AddControllerYawInput(Value);
}
}
void AMainPlayer::LookUpRate(float Rate)
{
//要乘以一个DeltaTime这样就可以避免高帧底帧差值问题
float Value = Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds();
if (Value != 0.f)
{
AddControllerPitchInput(Value);
}
}
限制角色上下视角旋转的范围
- 思路当旋转区域不是理想的范围就直接不要
cpp
void AMainPlayer::LookUp(float Value)
{
//UE_LOG(LogTemp, Warning, TEXT("%f"), GetControlRotation().Pitch);
//
//控制视角
if (GetControlRotation().Pitch < 270.f && GetControlRotation().Pitch >180.f && Value > 0.f)
{
return;
}
else if (GetControlRotation().Pitch < 180.f && GetControlRotation().Pitch >45.f && Value < 0.f)
{
return;
}
AddControllerPitchInput(Value);
}
- MainPlayer.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/CharacterMovementComponent.h"
// Sets default values
AMainPlayer::AMainPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
//设置SPringArm无碰撞臂长
SpringArm->TargetArmLength = 600.f;
SpringArm->bUsePawnControlRotation = true;//硬编码SpringArm继承controlller旋转为真
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(SpringArm, NAME_None);
FollowCamera->bUsePawnControlRotation = false;//硬编码FollowCamera继承controlller旋转为假
//设置胶囊体的默认宽高
GetCapsuleComponent()->SetCapsuleSize(35.f, 100.f);
//对Character的Pawn进行硬编码
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
//硬编码orient Rotation to Movement,给个默认转向速率
GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f);
//给键盘控制转向的速率变量赋初值
BaseTurnRate = 21.f;
BaseLookUpRate = 21.f;
}
// Called when the game starts or when spawned
void AMainPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMainPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMainPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//检查PlayerInputComponent指针,check函数只能在这使用
check(PlayerInputComponent);
//绑定移动轴映射事件
PlayerInputComponent->BindAxis("MoveForward", this, &AMainPlayer::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AMainPlayer::MoveRight);
//绑定Controller控制器去管理视角旋转
PlayerInputComponent->BindAxis("Turn", this, &AMainPlayer::Turn);
PlayerInputComponent->BindAxis("LookUp", this, &AMainPlayer::LookUp);
//绑定键盘鼠标轴映射事件
PlayerInputComponent->BindAxis("TurnRate", this, &AMainPlayer::TurnRate);
PlayerInputComponent->BindAxis("LookUpRate", this, &AMainPlayer::LookUpRate);
}
void AMainPlayer::MoveForward(float value)
{
if (Controller != nullptr && value != 0.f)
{
//获取到Control旋转
FRotator Rotation = Controller->GetControlRotation();
//转向只关注水平Yaw方向,因此置0防止影响
FRotator YowRotation = FRotator(0.0f, Rotation.Yaw, 0.0f);
//获取相机(鼠标控制器的朝向),并且朝这个轴的方向移动
FVector Direction = FRotationMatrix(YowRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, value);
}
}
void AMainPlayer::MoveRight(float value)
{
if (Controller != nullptr && value != 0.f)
{
//获取到Controller旋转
FRotator Rotation = Controller->GetControlRotation();
//转向只关注水平Yaw方向,因此置0防止影响
FRotator YowRotation = FRotator(0.0f, Rotation.Yaw, 0.0f);
//获取相机(鼠标控制器的朝向),并且朝这个轴的方向移动
FVector Direction = FRotationMatrix(YowRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(Direction, value);
}
}
void AMainPlayer::Turn(float Value)
{
if (Value != 0.f)
{
AddControllerYawInput(Value);
}
}
void AMainPlayer::LookUp(float Value)
{
//UE_LOG(LogTemp, Warning, TEXT("%f"), GetControlRotation().Pitch);
//
//控制视角
if (GetControlRotation().Pitch < 270.f && GetControlRotation().Pitch >180.f && Value > 0.f)
{
return;
}
else if (GetControlRotation().Pitch < 180.f && GetControlRotation().Pitch >45.f && Value < 0.f)
{
return;
}
AddControllerPitchInput(Value);
}
void AMainPlayer::TurnRate(float Rate)
{
//要乘以一个DeltaTime这样就可以避免高帧底帧差值问题
float Value = Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds();
if (Value != 0.f)
{
AddControllerYawInput(Value);
}
}
void AMainPlayer::LookUpRate(float Rate)
{
//要乘以一个DeltaTime这样就可以避免高帧底帧差值问题
float Value = Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds();
//控制视角
if (GetControlRotation().Pitch < 270.f && GetControlRotation().Pitch >180.f && Value > 0.f)
{
return;
}
else if (GetControlRotation().Pitch < 180.f && GetControlRotation().Pitch >45.f && Value < 0.f)
{
return;
}
AddControllerPitchInput(Value);
}
角色跳跃与空中控制
- 直接重写Character类中的Jump方法,然后绑定轴映射到空格跳跃
cpp
//重新Character类中的Jump方法
void Jump() override;
cpp
//绑定跳跃轴映射事件
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AMainPlayer::Jump);//按下空格
PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);//抬起空格
cpp
void AMainPlayer::Jump()
{
//继承父类的方法
Super::Jump();
}
- 设置跳跃的默认跳跃初始值与在空中的坠落时横向运动控制量(硬编码)
cpp
//设置跳跃初始值与在空中的坠落时横向运动控制量
GetCharacterMovement()->JumpZVelocity = 600.f;
GetCharacterMovement()->AirControl = 0.15f;
- MainPlayer.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MainPlayer.generated.h"
UCLASS()
class UEGAME_API AMainPlayer : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMainPlayer();
//新建一个SpringArm
UPROPERTY(visibleAnywhere,BlueprintReadOnly)
class USpringArmComponent* SpringArm;
//新建一个Camera
UPROPERTY(visibleAnywhere, BlueprintReadOnly)
class UCameraComponent* FollowCamera;
float BaseTurnRate; //使用键盘X转向的速率
float BaseLookUpRate; //使用键盘Y转向的速率
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
//重新Character类中的Jump方法
void Jump() override;
void MoveForward(float value);
void MoveRight(float value);
void Turn(float Value);
void LookUp(float Value);
void TurnRate(float Rate);
void LookUpRate(float Rate);
};
- MainPlayer.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/CharacterMovementComponent.h"
// Sets default values
AMainPlayer::AMainPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(GetRootComponent());
//设置SPringArm无碰撞臂长
SpringArm->TargetArmLength = 600.f;
SpringArm->bUsePawnControlRotation = true;//硬编码SpringArm继承controlller旋转为真
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(SpringArm, NAME_None);
FollowCamera->bUsePawnControlRotation = false;//硬编码FollowCamera继承controlller旋转为假
//设置胶囊体的默认宽高
GetCapsuleComponent()->SetCapsuleSize(35.f, 100.f);
//对Character的Pawn进行硬编码
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
//硬编码orient Rotation to Movement,给个默认转向速率
GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f);
//设置跳跃初始值与在空中的坠落时横向运动控制量
GetCharacterMovement()->JumpZVelocity = 600.f;
GetCharacterMovement()->AirControl = 0.15f;
//给键盘控制转向的速率变量赋初值
BaseTurnRate = 21.f;
BaseLookUpRate = 21.f;
}
// Called when the game starts or when spawned
void AMainPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMainPlayer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMainPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//检查PlayerInputComponent指针,check函数只能在这使用
check(PlayerInputComponent);
//绑定跳跃轴映射事件
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AMainPlayer::Jump);//按下空格
PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);//抬起空格
//绑定移动轴映射事件
PlayerInputComponent->BindAxis("MoveForward", this, &AMainPlayer::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AMainPlayer::MoveRight);
//绑定Controller控制器去管理视角旋转
PlayerInputComponent->BindAxis("Turn", this, &AMainPlayer::Turn);
PlayerInputComponent->BindAxis("LookUp", this, &AMainPlayer::LookUp);
//绑定键盘鼠标轴映射事件
PlayerInputComponent->BindAxis("TurnRate", this, &AMainPlayer::TurnRate);
PlayerInputComponent->BindAxis("LookUpRate", this, &AMainPlayer::LookUpRate);
}
void AMainPlayer::Jump()
{
//继承父类的方法
Super::Jump();
}
void AMainPlayer::MoveForward(float value)
{
if (Controller != nullptr && value != 0.f)
{
//获取到Control旋转
FRotator Rotation = Controller->GetControlRotation();
//转向只关注水平Yaw方向,因此置0防止影响
FRotator YowRotation = FRotator(0.0f, Rotation.Yaw, 0.0f);
//获取相机(鼠标控制器的朝向),并且朝这个轴的方向移动
FVector Direction = FRotationMatrix(YowRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, value);
}
}
void AMainPlayer::MoveRight(float value)
{
if (Controller != nullptr && value != 0.f)
{
//获取到Controller旋转
FRotator Rotation = Controller->GetControlRotation();
//转向只关注水平Yaw方向,因此置0防止影响
FRotator YowRotation = FRotator(0.0f, Rotation.Yaw, 0.0f);
//获取相机(鼠标控制器的朝向),并且朝这个轴的方向移动
FVector Direction = FRotationMatrix(YowRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(Direction, value);
}
}
void AMainPlayer::Turn(float Value)
{
if (Value != 0.f)
{
AddControllerYawInput(Value);
}
}
void AMainPlayer::LookUp(float Value)
{
//UE_LOG(LogTemp, Warning, TEXT("%f"), GetControlRotation().Pitch);
//
//控制视角
if (GetControlRotation().Pitch < 270.f && GetControlRotation().Pitch >180.f && Value > 0.f)
{
return;
}
else if (GetControlRotation().Pitch < 180.f && GetControlRotation().Pitch >45.f && Value < 0.f)
{
return;
}
AddControllerPitchInput(Value);
}
void AMainPlayer::TurnRate(float Rate)
{
//要乘以一个DeltaTime这样就可以避免高帧底帧差值问题
float Value = Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds();
if (Value != 0.f)
{
AddControllerYawInput(Value);
}
}
void AMainPlayer::LookUpRate(float Rate)
{
//要乘以一个DeltaTime这样就可以避免高帧底帧差值问题
float Value = Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds();
//控制视角
if (GetControlRotation().Pitch < 270.f && GetControlRotation().Pitch >180.f && Value > 0.f)
{
return;
}
else if (GetControlRotation().Pitch < 180.f && GetControlRotation().Pitch >45.f && Value < 0.f)
{
return;
}
AddControllerPitchInput(Value);
}
混合空间(BlendSpace)
- 创建BlendSpace1D,并给出相应的骨骼
- 将相应的行走、奔跑、动画添加上去
动画蓝图的创建
- 创建动画蓝图,选择自己的骨骼
创建给动画蓝图提供逻辑的AnimInstance子类
- 创建AnimInstance子类
- 写入判断是否奔跑与跳跃的变量,MainPlayer类的指针方便到时候好获取参数参与UE反射,重写NativeInitializeAnimation,这个函数类似与BeginPlay,然后加入一个实时更新的函数在Animation蓝图中使用
- MainPlayerAnimation.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "MainPlayerAnimInstance.generated.h"
/**
*
*/
UCLASS()
class UEGAME_API UMainPlayerAnimInstance : public UAnimInstance
{
GENERATED_BODY()
public:
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category="Animation Properties")
float Speed;//判断速度是否达到奔跑
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Animation Properties")
bool bIsAir;//判断是否跳跃
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Animation Properties")
class AMainPlayer* Player;
virtual void NativeInitializeAnimation() override; //类似与BeginPlay
UFUNCTION(BlueprintCallable, Category = "Animation Properties")
void UpdataAnimationProperties();//实时更新
};
- MainPlayerAnimtion.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayerAnimInstance.h"
void UMainPlayerAnimInstance::NativeInitializeAnimation()
{
}
void UMainPlayerAnimInstance::UpdataAnimationProperties()
{
}
编写动画参数更新逻辑并给动画蓝图指定父类
- MainPlayerAnimtion.cpp
- TryGetPawnOwner:获取角色的Pawn类
- GetVelocity:获取速度
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MainPlayerAnimInstance.h"
#include "Characters/Player/MainPlayer.h"
#include "GameFramework/CharacterMovementComponent.h"
void UMainPlayerAnimInstance::NativeInitializeAnimation()
{
Player = Cast<AMainPlayer>(TryGetPawnOwner());//获取角色的Pawn类
}
void UMainPlayerAnimInstance::UpdataAnimationProperties()
{
//防御性编程
if (Player)
{
//移动只需要平面的速度
FVector SpeedVector = Player->GetVelocity();
FVector PlanarSpeed = FVector(SpeedVector.X, SpeedVector.Y, 0.f);
//将移动的向量传给speed即可
Speed = PlanarSpeed.Size();
bIsAir = Player->GetMovementComponent()->IsFalling();//判断Player是否在下落
}
else
{
Player = Cast<AMainPlayer>(TryGetPawnOwner());//获取角色的Pawn类
}
}
- 给动画蓝图指定父类
制作移动动画设置到角色
- 连接我们的更新函数
- 新建一个状态机
- 在状态机里面在添加一个状态
- 然后再到此状态里面把混合空间与编码的speed加上
- 返回最开始的动画图表连接上最终动画
- 最后将混合空间添加到角色蓝图Mesh的Animation中就可
制作跳跃动画设置到角色
-
将跳跃的三个状态添加到状态机中
-
首先判断是否起跳,用C++编写好的变量进行判断
-
监测起跳动作,当跳跃动作快播放完了的时候就得开始切换,一般我们常用这个Timer Remaining(ratio):剩余计时器(比例)来进行使用判断监测
-
判断是否落下
-
监测落下动作,当跳跃动作快播放完了的时候就得开始切换,一般我们常用这个Timer Remaining(ratio):剩余计时器(比例)来进行使用判断监测
-
运行结果