虚幻C+++基础 day2

角色移动与视角控制

Character类与相关API

  • 创建Character子类
  • MainPlayer.h
// 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
// 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+++基础 day2_第1张图片

指定骨骼模型并调整胶囊体

  • 指定骨骼模型

虚幻C+++基础 day2_第2张图片

  • C++硬编码给出默认值

  • 头文件胶囊体#include “Components/CapsuleComponent.h”

//设置胶囊体的默认宽高
GetCapsuleComponent()->SetCapsuleSize(35.f, 100.f);

虚幻C+++基础 day2_第3张图片

创建轴映射与GameMode

  • 创建关卡GameMode子类

虚幻C+++基础 day2_第4张图片

  • 设置玩家使用默认类

虚幻C+++基础 day2_第5张图片

虚幻C+++基础 day2_第6张图片

  • 轴映射

虚幻C+++基础 day2_第7张图片

基本简单移动与旋转控制

  • AddMovementInput:沿着给定的世界方向向量(通常是标准化的)添加移动输入,并按“ScaleValue”进行缩放。如果ScaleValue < 0,则移动方向相反。基础Pawn类不会自动应用移动,这取决于用户在Tick事件中这样做。像Character和DefaultPawn这样的子类会自动处理这些输入并移动。

虚幻C+++基础 day2_第8张图片

  • GetActorForwardVector:获取Actor,X轴正向的向量

  • GetActorRightVector:获取Actor,Y轴正向的向量

MainPlayer.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的控制器
    虚幻C+++基础 day2_第9张图片
// 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就开启自动面向旋转

虚幻C+++基础 day2_第10张图片

  • 头文件:#include “GameFramework/CharacterMovementComponent.h”
	//硬编码orient Rotation to Movement,给个默认转向速率
	GetCharacterMovement()->bOrientRotationToMovement = true;
	GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f);
  • 运行结果

虚幻C+++基础 day2_第11张图片

创建键盘与手柄使用的视角与旋转函数

  • 新建两个float变量来控制上下左右转向的速率,注意旋转时要乘以DeltaTime避免高低性能差值
	float BaseTurnRate;		//使用键盘X转向的速率
	float BaseLookUpRate;	//使用键盘Y转向的速率

	//给键盘控制转向的速率变量赋初值
	BaseTurnRate = 21.f;
	BaseLookUpRate = 21.f;
  • 因为可能要修改视角限制,新建Turn与LookUp绑定Controller控制器去管理视角旋转函数,新建绑定键盘鼠标轴映射事件函数
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);
// 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::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);
	}
}

限制角色上下视角旋转的范围

  • 思路当旋转区域不是理想的范围就直接不要

虚幻C+++基础 day2_第12张图片

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
// 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方法,然后绑定轴映射到空格跳跃

虚幻C+++基础 day2_第13张图片

虚幻C+++基础 day2_第14张图片
虚幻C+++基础 day2_第15张图片

	//重新Character类中的Jump方法
	void Jump() override;
	//绑定跳跃轴映射事件
	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AMainPlayer::Jump);//按下空格
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);//抬起空格
void AMainPlayer::Jump()
{
	//继承父类的方法
	Super::Jump();
}
  • 设置跳跃的默认跳跃初始值与在空中的坠落时横向运动控制量(硬编码)
	//设置跳跃初始值与在空中的坠落时横向运动控制量
	GetCharacterMovement()->JumpZVelocity = 600.f;
	GetCharacterMovement()->AirControl = 0.15f;

虚幻C+++基础 day2_第16张图片

  • MainPlayer.h
// 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
// 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,并给出相应的骨骼

虚幻C+++基础 day2_第17张图片

  • 将相应的行走、奔跑、动画添加上去

虚幻C+++基础 day2_第18张图片

动画蓝图的创建

  • 创建动画蓝图,选择自己的骨骼
    虚幻C+++基础 day2_第19张图片
    虚幻C+++基础 day2_第20张图片

创建给动画蓝图提供逻辑的AnimInstance子类

  • 创建AnimInstance子类
    虚幻C+++基础 day2_第21张图片
  • 写入判断是否奔跑与跳跃的变量,MainPlayer类的指针方便到时候好获取参数参与UE反射,重写NativeInitializeAnimation,这个函数类似与BeginPlay,然后加入一个实时更新的函数在Animation蓝图中使用
  • MainPlayerAnimation.h
// 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
// 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:获取速度
// 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类
	}

}
  • 给动画蓝图指定父类
    虚幻C+++基础 day2_第22张图片

制作移动动画设置到角色

  • 连接我们的更新函数
    虚幻C+++基础 day2_第23张图片
  • 新建一个状态机
    虚幻C+++基础 day2_第24张图片
  • 在状态机里面在添加一个状态
    虚幻C+++基础 day2_第25张图片
  • 然后再到此状态里面把混合空间与编码的speed加上
    虚幻C+++基础 day2_第26张图片
  • 返回最开始的动画图表连接上最终动画
    虚幻C+++基础 day2_第27张图片
  • 最后将混合空间添加到角色蓝图Mesh的Animation中就可
    虚幻C+++基础 day2_第28张图片

制作跳跃动画设置到角色

  • 将跳跃的三个状态添加到状态机中
    虚幻C+++基础 day2_第29张图片

  • 首先判断是否起跳,用C++编写好的变量进行判断
    虚幻C+++基础 day2_第30张图片

  • 监测起跳动作,当跳跃动作快播放完了的时候就得开始切换,一般我们常用这个Timer Remaining(ratio):剩余计时器(比例)来进行使用判断监测
    虚幻C+++基础 day2_第31张图片

  • 判断是否落下
    虚幻C+++基础 day2_第32张图片

  • 监测落下动作,当跳跃动作快播放完了的时候就得开始切换,一般我们常用这个Timer Remaining(ratio):剩余计时器(比例)来进行使用判断监测
    虚幻C+++基础 day2_第33张图片

  • 运行结果

你可能感兴趣的:(UE,C呱呱,虚幻,c++,ue4)