【UE5 C++课程系列笔记】04——创建可操控的Pawn

发布于:2024-11-29 ⋅ 阅读:(24) ⋅ 点赞:(0)

根据官方文档创建一个可以控制前后左右移动、旋转视角、缩放视角的Pawn 。

步骤 

一、创建Pawn 

1. 新建一个C++类,继承Pawn类,这里命名为“PawnWithCamera”

2. 在头文件中申明弹簧臂、摄像机和静态网格体组件

3. 在源文件中引入组件所需库

 

在构造函数中创建组件实例

将StaticMesh组件附加在根组件上,再将SpringArm组件附加在StaticMesh组件上,最后将Camera组件附加在SpringArm组件的末端

设置一下SpringArm组件的相对位置和旋转、弹簧臂长度、开启相机滞后、相机滞后速度

设置自动控制该Pawn

4. 编译好后,创建基于“PawnWithCamera”的蓝图类“BP_PawnWithCamera”

将“BP_PawnWithCamera”拖入视口

然后运行,可以看到我们此时视角就是“BP_PawnWithCamera”中Camera组件的视角了,但是我们现在还无法通过鼠标键盘去操控这个Pawn。

二、操控Pawn

1. 打开项目设置,添加操作映射和轴映射如下,完成输入绑定

2. 下面开始响应输入。在头文件中定义如下输入变量

定义如下输入函数

在源文件中实现输入函数

现在已经有了存储输入数据的函数,接着要告知引擎何时调用该代码。需要把Pawn的输入事件和函数相互绑定:

在Tick中处理视角缩放逻辑,当按下鼠标右键时按钮时进行放大,否则恢复正常。

继续编辑旋转逻辑

最后编辑移动逻辑如下

此时就完成了Pawn的前后左右移动、旋转视角、缩放视角的功能了。

完整代码如下:

PawnWithCamera.h

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "PawnWithCamera.generated.h"

UCLASS()
class STUDY_API APawnWithCamera : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	APawnWithCamera();

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;

protected:
	void MoveForward(float AxisValue);
	void MoveRight(float AxisValue);
	void PitchCamera(float AxisValue);
	void YawCamera(float AxisValue);
	void ZoomIn();
	void ZoomOut();

protected:
	UPROPERTY(EditAnywhere)
	class USpringArmComponent* SpringArmComp;
	UPROPERTY(EditAnywhere)
	class UCameraComponent* CameraComp;
	UPROPERTY(EditAnywhere)
	class UStaticMeshComponent* StaticMeshComp;

	FVector2D MovementInput;
	FVector2D CameraInput;
	float ZoomFactor = 1.0f;
	bool bZoomingIn = false;

};

PawnWithCamera.cpp

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


#include "GameCamera/PawnWithCamera.h"

#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/StaticMeshComponent.h"

// Sets default values
APawnWithCamera::APawnWithCamera()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	//创建组件
	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootSenceComponent"));
	StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComponent"));
	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComponent"));
	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));

	//绑定组件
	StaticMeshComp->SetupAttachment(RootComponent);
	SpringArmComp->SetupAttachment(StaticMeshComp);
	CameraComp->SetupAttachment(SpringArmComp, USpringArmComponent::SocketName);

	//设置SpringArm
	SpringArmComp->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));
	SpringArmComp->TargetArmLength = 400.0f;
	SpringArmComp->bEnableCameraLag = true;
	SpringArmComp->CameraLagSpeed = 3.0f;

	//设置默认控制玩家为本Pawn
	AutoPossessPlayer = EAutoReceiveInput::Player0;

}

// Called when the game starts or when spawned
void APawnWithCamera::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void APawnWithCamera::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	{
		if (bZoomingIn)
		{
			ZoomFactor += DeltaTime / 0.5f;
		}
		else
		{
			ZoomFactor -= DeltaTime / 0.25f;
		}
		ZoomFactor = FMath::Clamp<float>(ZoomFactor, 0.0f, 1.0f);

		//根据ZoomFactor来设置摄像机的时长和弹簧臂的长度
		CameraComp->FieldOfView = FMath::Lerp<float>(90.0f, 60.0f, ZoomFactor);
		SpringArmComp->TargetArmLength = FMath::Lerp<float>(400.0f, 300.0f, ZoomFactor);
	}
	
	//旋转Actor的偏转角度,这样摄像机也能旋转,因为摄像机与Actor相互绑定
	{
		FRotator NewRotation = GetActorRotation();
		NewRotation.Yaw += CameraInput.X;
		SetActorRotation(NewRotation);
	}
	//旋转摄像机的俯仰角度,但要对其进行限制,这样我们就能始终俯视Actor
	{
		FRotator NewRotation = SpringArmComp->GetComponentRotation();
		NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -80.0f, -15.0f);
		SpringArmComp->SetWorldRotation(NewRotation);
	}

	//基于“MoveX”和“MoveY”坐标轴来处理移动
	if (!MovementInput.IsZero())
	{
		//把移动轴的输入数值放大100倍
		MovementInput = MovementInput.GetSafeNormal() * 100.0f;
		FVector NewLocation = GetActorLocation();
		NewLocation += GetActorForwardVector() * MovementInput.X * DeltaTime;
		NewLocation += GetActorRightVector() * MovementInput.Y * DeltaTime;
		SetActorLocation(NewLocation);
	}
}

// Called to bind functionality to input
void APawnWithCamera::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	//绑定“ZoomIn”的事件
	InputComponent->BindAction("ZoomIn", IE_Pressed, this, &APawnWithCamera::ZoomIn);
	InputComponent->BindAction("ZoomIn", IE_Released, this, &APawnWithCamera::ZoomOut);

	//为四条轴绑定事件(每帧调用)
	InputComponent->BindAxis("MoveForward", this, &APawnWithCamera::MoveForward);
	InputComponent->BindAxis("MoveRight", this, &APawnWithCamera::MoveRight);
	InputComponent->BindAxis("CameraPitch", this, &APawnWithCamera::PitchCamera);
	InputComponent->BindAxis("CameraYaw", this, &APawnWithCamera::YawCamera);

}

void APawnWithCamera::MoveForward(float AxisValue)
{
	MovementInput.X = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
}

void APawnWithCamera::MoveRight(float AxisValue)
{
	MovementInput.Y = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
}

void APawnWithCamera::PitchCamera(float AxisValue)
{
	CameraInput.Y = AxisValue;
}

void APawnWithCamera::YawCamera(float AxisValue)
{
	CameraInput.X = AxisValue;
}

void APawnWithCamera::ZoomIn()
{
	bZoomingIn = true;
}

void APawnWithCamera::ZoomOut()
{
	bZoomingIn = false;
}

官方参考文档:

https://dev.epicgames.com/documentation/zh-cn/unreal-engine/quick-start-guide-to-player-controlled-cameras-in-unreal-engine-cpp?application_version=5.3