虚幻C+++基础 day2

news2025/1/4 18:46:27

角色移动与视角控制

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++硬编码给出默认值

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

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

在这里插入图片描述

创建轴映射与GameMode

  • 创建关卡GameMode子类

在这里插入图片描述

  • 设置玩家使用默认类

在这里插入图片描述

在这里插入图片描述

  • 轴映射

在这里插入图片描述

基本简单移动与旋转控制

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

在这里插入图片描述

  • 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的控制器
    在这里插入图片描述
// 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”
	//硬编码orient Rotation to Movement,给个默认转向速率
	GetCharacterMovement()->bOrientRotationToMovement = true;
	GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f);
  • 运行结果

在这里插入图片描述

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

  • 新建两个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);
	}
}

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

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

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

	//重新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;

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

动画蓝图的创建

  • 创建动画蓝图,选择自己的骨骼
    在这里插入图片描述
    在这里插入图片描述

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

  • 创建AnimInstance子类
    在这里插入图片描述
  • 写入判断是否奔跑与跳跃的变量,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类
	}

}
  • 给动画蓝图指定父类
    在这里插入图片描述

制作移动动画设置到角色

  • 连接我们的更新函数
    在这里插入图片描述
  • 新建一个状态机
    在这里插入图片描述
  • 在状态机里面在添加一个状态
    在这里插入图片描述
  • 然后再到此状态里面把混合空间与编码的speed加上
    在这里插入图片描述
  • 返回最开始的动画图表连接上最终动画
    在这里插入图片描述
  • 最后将混合空间添加到角色蓝图Mesh的Animation中就可
    在这里插入图片描述

制作跳跃动画设置到角色

  • 将跳跃的三个状态添加到状态机中
    在这里插入图片描述

  • 首先判断是否起跳,用C++编写好的变量进行判断
    在这里插入图片描述

  • 监测起跳动作,当跳跃动作快播放完了的时候就得开始切换,一般我们常用这个Timer Remaining(ratio):剩余计时器(比例)来进行使用判断监测
    在这里插入图片描述

  • 判断是否落下
    在这里插入图片描述

  • 监测落下动作,当跳跃动作快播放完了的时候就得开始切换,一般我们常用这个Timer Remaining(ratio):剩余计时器(比例)来进行使用判断监测
    在这里插入图片描述

  • 运行结果
    请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173934.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7.0+最快速安装docker的方法

先安装yum工具&#xff0c;然后添加阿里云的docker仓库&#xff0c;然后yum安装&#xff0c;然后启动 安装yum-config yum install yum-utils -y yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum install docker-ce do…

一款简单而强大的文档翻译网站

一款文字/文件翻译的网站,支持多个领域的翻译&#xff0c;支持常见的语言翻译(韩/日/法/英/俄/德…),最大百分比的保持原文排版(及个别除外基本100%还原)。 新用户注册就有100页的免费额度&#xff0c;每月系统还会随机赠送翻译额度&#xff0c;说实话这比好多的企业要好的多了…

为什么没有面试机会?是因为你没有掌握这套完整的性能测试流程,

一、准备工作 在什么阶段开展性能测试工作&#xff1f;一般情况下&#xff0c;是在被测系统已完成功能测试、系统趋于稳定的情况下&#xff0c;才会进行性能测试。 1. 组建测试团队 根据被测系统的实际情况&#xff0c;组建一个性能测试团队&#xff0c;团队成员包括&#xff…

CUMT-----Java课后第五章编程作业

文章目录 一、题11.1 问题描述1.2 代码块1.3 运行截图 二、题22.1 问题描述2.2 代码块2.3 运行截图 一、题1 1.1 问题描述 (1)使用继承编写人类、教师、学生类的实体类。(2)编写测试类&#xff0c;实例化教师和学生类对象并显示。 1.2 代码块 public class Human {private S…

镭神智能C16的ROS驱动的安装方法

原文链接 前言 激光雷达赶上了自动驾驶了浪潮&#xff0c;国产激光雷达也越来越多。 最近团队要购买激光雷达&#xff0c;正好拿镭神智能的产品测试一下&#xff0c;安装驱动是首先要做的&#xff0c;因此在这里记录一下。 产品说明&#xff1a;http://www.leishen-lidar.com…

multiple kernel learning(MKL)多核学习

历史上之所以会出现多核学习&#xff08;MKL&#xff09;这个词&#xff0c;是因为在深度学习流行起来以前&#xff0c;kernel是处理非线性的默认方法&#xff0c;那个年代优化一个非线性函数不容易&#xff0c;每加一层复杂性可能就需要多设计一个优化算法&#xff0c;MKL就是…

使用 ChatGPT 提升 LeetCode 刷题效率

文章目录 1 背景2 操作步骤 1 背景 在做 LeetCode 的 SQL 题库时, 想在本地调试, 需要在本地的数据库上创建表以及准备测试数据, 大家都是有经验的开发人员, 简单粗暴的办法就不讲了 可以借助 ChatGPT 的能力, 生产数据库的表以及测试数据的 sql, 提升刷题效率 2 操作步骤 将…

K8S知识点(四)

&#xff08;1&#xff09;环境搭建-集群安装 查看所需镜像 定义下载镜像 循环下载镜像&#xff1a; 下载完成之后&#xff1a;查看一下镜像&#xff0c;名字也已经改成了k8s的名字 集群初始化只在master节点上运行&#xff0c; 出现sucessfully表示成功&#xff0c;提示要运…

5.3 连接和分离线程

方法 pthread_join(thread, status) pthread_detach(thread) pthread_attr_setdetachstate(attr, detachstate) pthread_attr_getdetachstate(attr) 连接 连接&#xff08;joining&#xff09;是一种线程之间完成同步的方法&#xff0c;举例如下。 pthread_join()方法会阻…

Ultra:知识图谱推理的基础模型

一、说明 训练单个通用模型来解决任意数据集始终是 ML 研究人员的梦想&#xff0c;尤其是在基础模型时代。虽然这些梦想已经在图像或自然语言等感知领域实现了&#xff0c;但它们是否可以在推理领域&#xff08;如图形&#xff09;中再现仍然是一个开放的挑战。 图片由作者根据…

PDUR IPDUM

步骤1&#xff1a;思考问题 PDUR&#xff08;PDU Router&#xff09;&#xff1a;PDUR是负责消息的路由和转发。PDUR模块接收来自上层的消息&#xff0c;并根据预定义的路由规则将消息转发给相应的下层模块&#xff0c;或者将从下层接收到的消息转发给相应的上层模块。 PDUR的主…

SOEM源码解析——ecx_init_context(初始化句柄)

0 工具准备 1.SOEM-master-1.4.0源码1 ecx_init_context函数总览 /*** brief 初始化句柄* param context 句柄*/ void ecx_init_context(ecx_contextt *context) {int lp;*(context->slavecount) 0;/* clean ec_slave array *//* 清空从站信息数组 */memset(context->…

python-在系统托盘显示CPU使用率和内存使用率

一、添加轮子 1.添加托盘区图标库 infi.systray from infi.systray import SysTrayIcon 2.添加图像处理库 Pillow from PIL import Image, ImageDraw, ImageFont 3.添加 psutil 来获取CPU、内存信息 import psutil 二、完整代码 from infi.systray import SysTrayIcon …

简单-【1 绪论】

关键字&#xff1a; 数据类型、数据结构定义、递归关键、线性结构、非线性结构、算法特性、算法目标、时间复杂度排序

【异常错误】Multiple top-level packages discovered in a flat-layout: [

今天在配置环境时&#xff0c;在运行代码&#xff1a; pip install -e . 出现了以下错误&#xff1a; 解决方案 在setup.py中显示加入一行 py_modules[]&#xff0c;如&#xff1a; setup(namexxxx,versionx.x,py_modules[], ) 再次运行pip指令安装即可解决。 error: Mul…

由于找不到msvcr110.dll无法继续执行此代码怎么解决?5个解决方法分享

MSVCP110.dll是Microsoft Visual C 2012运行时库的一部分&#xff0c;它包含了许多用于支持C应用程序运行的函数。当您在运行某些程序时&#xff0c;可能会遇到“msvcp110.dll丢失”的错误提示。为了解决这个问题&#xff0c;您可以尝试以下5种方法&#xff1a; 方法1. 重新安装…

思维模型 霍布森选择效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。这是一个设计好的陷阱&#xff0c;也许你认为你有选择&#xff0c;然后冥冥之中你的选择却很少&#xff0c;尽在所谓的“命运”掌握之中。 1 霍布森选择效应的应用 1.1 iphone的营销策略之…

为什么说IT企业知识库是知识共享的驱动力?

在快速发展和不断变化的IT行业中&#xff0c;知识的积累和共享是保持竞争力的关键。一个完善的知识库可以帮助企业有效管理和传承内部知识&#xff0c;提高团队的工作效率和协作能力。随着企业规模的扩大和员工的流动性增加&#xff0c;一个完善的知识库可以确保知识的传承和持…

leetcode 684. 冗余连接

树可以看成是一个连通且 无环 的 无向 图。 给定往一棵 n 个节点 (节点值 1&#xff5e;n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间&#xff0c;且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges &#xff0c;edges[i] …

阿里云域名实战

一、准备阿里云服务器&#xff0c;实现网站功能 &#xff08;1&#xff09;百度搜索阿里云 &#xff08;2&#xff09;登录阿里云 可以使用支付宝&#xff0c;淘宝账号登录 &#xff08;3&#xff09;点击控制台 (4)创建实例&#xff0c;购买云服务器 &#xff08;5&#x…