C++创建Pawn类玩家
- 创建一个GameMode蓝图用来加载我们自定义的游戏Mode
- 新建一个Pawn的C++,
MyCharacter
类作为玩家,新建一个相机组件与相机臂组件,box组件作为根组件
cpp
复制代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MyCharacter.generated.h"
UCLASS()
class CITYTWIN_API AMyCharacter : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyCharacter();
//box作为根组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class UBoxComponent* CollisionBox;
//相机组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class UCameraComponent* FollowCamera;
//相机臂组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class USpringArmComponent* CameraBoom;
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;
};
cpp
复制代码
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyCharacter.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// 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;
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
CollisionBox->SetupAttachment(GetRootComponent());
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(CollisionBox);
CameraBoom->TargetArmLength = 1500.f;
CameraBoom->bUsePawnControlRotation = false;
CameraBoom->bEnableCameraLag = true;//摄像机臂平滑
CameraBoom->bEnableCameraRotationLag = true;//启用相机旋转延迟
CameraBoom->bDoCollisionTest = false;//关闭摄像机臂碰撞
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom);
FollowCamera->bUsePawnControlRotation = false;
}
// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
- 创建这个Pawn类的蓝图进行之前登录页面动画的视角旋转方向问题的解决
- 首先将蓝图生成对齐到视角
- 将Pawn类自动接收玩家0
- 然后删除PlayerStart
- 运行结果
移动增强输入系统
- 在项目建立.cs文件中添加这个模块
- 绑定增强输入系统操作
MyCharacter.h
cpp
复制代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "../../../../UE_5.2.1/UE_5.2/Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/InputActionValue.h"
#include "MyCharacter.generated.h"
UCLASS()
class CITYTWIN_API AMyCharacter : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyCharacter();
//box作为根组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class UBoxComponent* CollisionBox;
//相机组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class UCameraComponent* FollowCamera;
//相机臂组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class USpringArmComponent* CameraBoom;
//绑定映射
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputMappingContext* MappingContext;
//移动绑定
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* LeftButtonAction;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
//鼠标按下操作事件
void LeftMouseDown(const FInputActionValue& value);
void LeftMouseUp(const FInputActionValue& value);
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};
cpp
复制代码
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyCharacter.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// 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;
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
CollisionBox->SetupAttachment(GetRootComponent());
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(CollisionBox);
CameraBoom->TargetArmLength = 1500.f;
CameraBoom->bUsePawnControlRotation = false;
CameraBoom->bEnableCameraLag = true;//摄像机臂平滑
CameraBoom->bEnableCameraRotationLag = true;//启用相机旋转延迟
CameraBoom->bDoCollisionTest = false;//关闭摄像机臂碰撞
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom);
FollowCamera->bUsePawnControlRotation = false;
}
// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
APlayerController* PlayerController = Cast<APlayerController>(Controller);
if (PlayerController)
{
UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
if (Subsystem)
{
Subsystem->AddMappingContext(MappingContext, 0);
}
}
}
void AMyCharacter::LeftMouseDown(const FInputActionValue& value)
{
}
void AMyCharacter::LeftMouseUp(const FInputActionValue& value)
{
}
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EnhancedInputConponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (EnhancedInputConponent)
{
EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Started, this, &AMyCharacter::LeftMouseDown);
EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::LeftMouseUp);
}
}
获取鼠标位置坐标与鼠标移动后的差量
- 使用
GetMousePosition
函数来获取鼠标的坐标点
- 在
MyCharacter.h
中新建一个函数专门用来获取鼠标的坐标点的函数
cpp
复制代码
//鼠标的坐标点
FVector2D MousePos = FVector2D::ZeroVector;
void GetMousePosition();
cpp
复制代码
void AMyCharacter::GetMousePosition()
{
GetWorld()->GetFirstPlayerController()->GetMousePosition(MousePos.X, MousePos.Y);
//打印鼠标信息到屏幕
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, FString::Printf(TEXT("%f,%f"), MousePos.X, MousePos.Y));
}
- 获取鼠标变化差量,当我们鼠标变化时,我们要获取到这个变化的差量值,我们可以定义两个变量,一个变量存储
用来作为变化之前的绝对位置减去变化之后的当前绝对位置
,然后另外两个变量来存储变化之后当前的绝对位置
cpp
复制代码
//鼠标的坐标点
FVector2D MousePos = FVector2D::ZeroVector;
//记录的鼠标变化差量
FVector2D MouseVariationDifference = FVector2D::ZeroVector;
//记录变化之后的鼠标坐标
float MouseX = 0.f;
float MouseY = 0.f;
void AMyCharacter::GetMousePosition()
{
//获取当前鼠标移动坐标
GetWorld()->GetFirstPlayerController()->GetMousePosition(MousePos.X, MousePos.Y);
//记录的鼠标变化差量
MouseVariationDifference = MousePos - FVector2D(MouseX, MouseY);
//记录变化后的鼠标位置
MouseX = MousePos.X;
MouseY = MousePos.Y;
//打印鼠标信息到屏幕
GEngine->AddOnScreenDebugMessage(1, 1, FColor::Red, FString::Printf(TEXT("%f,%f"), MousePos.X, MousePos.Y));
GEngine->AddOnScreenDebugMessage(2, 1, FColor::Yellow, FString::Printf(TEXT("%f,%f"), MouseVariationDifference.X, MouseVariationDifference.Y));
}
设置滑动鼠标实现旋转视角效果
- 通过获取的移动的鼠标差量进行鼠标滑动移动视角
- 新建一个鼠标视角移动速度变量,用来控制鼠标实现视角旋转的移动速度
cpp
复制代码
//鼠标视角移动速度
float MouseSpeed = 0.1f;
- 新建一个鼠标视角移动函数,函数逻辑
ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)
:Pitch是虚幻中的抬头与低头,在直角坐标系中用来Y来描述
ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f)
:Yaw是摇头转向,在直角坐标系中用来X来描述,实践中得乘以-1使用,估计是因为虚幻默认以右方向为正方向的原因
cpp
复制代码
//鼠标移动视角移动事件
void MouseMove();
void AMyCharacter::MouseMove()
{
FRotator ActorRotator = GetActorRotation();
FRotator NewActorRotator = FRotator(ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed),
ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
SetActorRotation(NewActorRotator);
}
cpp
复制代码
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//获取鼠标坐标
GetMousePosition();
//鼠标移动视角
MouseMove();
}
- 运行结果
鼠标左键视觉拖动效果
- 将滑动鼠标实现旋转视角效果设置为鼠标左键按下后才能实现
- 添加一个布尔变量用来标识是否要开启鼠标旋转视角事情
cpp
复制代码
//标识鼠标左键是否按下
bool bIsMouseLeftDown = false;
void AMyCharacter::MouseMove()
{
if (bIsMouseLeftDown)
{
FRotator ActorRotator = GetActorRotation();
//限制一下视角度数带来的错误
FRotator NewActorRotator = FRotator(FMath::Clamp((ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)),-80.f,-10.f),
ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
SetActorRotation(NewActorRotator);
}
}
void AMyCharacter::LeftMouseDown(const FInputActionValue& value)
{
bIsMouseLeftDown = true;
}
void AMyCharacter::LeftMouseUp(const FInputActionValue& value)
{
bIsMouseLeftDown = false;
}
鼠标右键视角移动效果
- 添加右键的输入操作
- 新建右键是否按下的标识布尔变量,创建右键操作的输入行为,即绑定函数
cpp
复制代码
//移动绑定
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* RightButtonAction;
//标识鼠标右键是否按下
bool bIsMouseRightDown = false;
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EnhancedInputConponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (EnhancedInputConponent)
{
EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Started, this, &AMyCharacter::LeftMouseDown);
EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::LeftMouseUp);
EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Started, this, &AMyCharacter::RightMouseDown);
EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::RightMouseUp);
}
}
void AMyCharacter::RightMouseDown(const FInputActionValue& value)
{
bIsMouseRightDown = true;
}
void AMyCharacter::RightMouseUp(const FInputActionValue& value)
{
bIsMouseRightDown = false;
}
cpp
复制代码
//鼠标右键移动速度
float MouseRightSpeed = 100.f;
void AMyCharacter::MouseMove()
{
if (bIsMouseLeftDown)
{
FRotator ActorRotator = GetActorRotation();
//限制一下视角度数带来的错误
FRotator NewActorRotator = FRotator(FMath::Clamp((ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)),-80.f,-10.f),
ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
SetActorRotation(NewActorRotator);
}
if (bIsMouseRightDown)
{
FVector SpeedMove = FVector(MouseVariationDifference.Y * MouseRightSpeed,
-1.0 * MouseRightSpeed * MouseVariationDifference.X, 0);
AddActorLocalOffset(SpeedMove);
//限制z轴
FVector Location = GetActorLocation();
FVector NewLocation = FVector(Location.X, Location.Y, 4520);
SetActorLocation(NewLocation);
}
}
鼠标中键控制摄像机臂长度,缩放地图效果
- 新建鼠标中键的操作行为,添加一个鼠标中键移动速度变量,然后在鼠标中键操作事件中完成逻辑,逻辑是获取相机臂的长度,用获取鼠标滚轮的量值乘以鼠标中键移动速度变量被获取的相机臂原长度减去
cpp
复制代码
//移动绑定
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* MiddleButtonAction;
//鼠标中键移动速度
float MouseMiddleSpeed = 1000.f;
void AMyCharacter::MiddleMouseSlide(const FInputActionValue& value)
{
float Axis = value.Get<float>();
float CameraArm = CameraBoom->TargetArmLength;
//限制相机臂长度
CameraBoom->TargetArmLength = FMath::Clamp((CameraArm - Axis * MouseMiddleSpeed), 1000.f, 30000.f);
}
- 运行结果
源码
MyCharacter.h
cpp
复制代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "../../../../UE_5.2.1/UE_5.2/Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/InputActionValue.h"
#include "MyCharacter.generated.h"
UCLASS()
class CITYTWIN_API AMyCharacter : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyCharacter();
//box作为根组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class UBoxComponent* CollisionBox;
//相机组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class UCameraComponent* FollowCamera;
//相机臂组件
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
class USpringArmComponent* CameraBoom;
//绑定映射
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputMappingContext* MappingContext;
//移动绑定
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* LeftButtonAction;
//移动绑定
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* RightButtonAction;
//移动绑定
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
class UInputAction* MiddleButtonAction;
//鼠标的坐标点
FVector2D MousePos = FVector2D::ZeroVector;
//记录的鼠标变化差量
FVector2D MouseVariationDifference = FVector2D::ZeroVector;
//记录变化之后的鼠标坐标
float MouseX = 0.f;
float MouseY = 0.f;
//鼠标视角移动速度
float MouseSpeed = 0.1f;
//鼠标右键移动速度
float MouseRightSpeed = 100.f;
//鼠标中键移动速度
float MouseMiddleSpeed = 1000.f;
//标识鼠标左键是否按下
bool bIsMouseLeftDown = false;
//标识鼠标右键是否按下
bool bIsMouseRightDown = false;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
//鼠标按下操作事件
void LeftMouseDown(const FInputActionValue& value);
void LeftMouseUp(const FInputActionValue& value);
void RightMouseDown(const FInputActionValue& value);
void RightMouseUp(const FInputActionValue& value);
void MiddleMouseSlide(const FInputActionValue& value);
//鼠标移动视角移动事件
void MouseMove();
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void GetMousePosition();
};
MyCharacter.cpp
cpp
复制代码
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyCharacter.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "Engine/Engine.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// 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;
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
CollisionBox->SetupAttachment(GetRootComponent());
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(CollisionBox);
CameraBoom->TargetArmLength = 1500.f;
CameraBoom->bUsePawnControlRotation = false;
CameraBoom->bEnableCameraLag = true;//摄像机臂平滑
CameraBoom->bEnableCameraRotationLag = true;//启用相机旋转延迟
CameraBoom->bDoCollisionTest = false;//关闭摄像机臂碰撞
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom);
FollowCamera->bUsePawnControlRotation = false;
}
// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
APlayerController* PlayerController = Cast<APlayerController>(Controller);
if (PlayerController)
{
UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
if (Subsystem)
{
Subsystem->AddMappingContext(MappingContext, 0);
}
}
}
void AMyCharacter::LeftMouseDown(const FInputActionValue& value)
{
bIsMouseLeftDown = true;
}
void AMyCharacter::LeftMouseUp(const FInputActionValue& value)
{
bIsMouseLeftDown = false;
}
void AMyCharacter::RightMouseDown(const FInputActionValue& value)
{
bIsMouseRightDown = true;
}
void AMyCharacter::RightMouseUp(const FInputActionValue& value)
{
bIsMouseRightDown = false;
}
void AMyCharacter::MiddleMouseSlide(const FInputActionValue& value)
{
float Axis = value.Get<float>();
float CameraArm = CameraBoom->TargetArmLength;
//限制相机臂长度
CameraBoom->TargetArmLength = FMath::Clamp((CameraArm - Axis * MouseMiddleSpeed), 1000.f, 30000.f);
}
void AMyCharacter::MouseMove()
{
if (bIsMouseLeftDown)
{
FRotator ActorRotator = GetActorRotation();
//限制一下视角度数带来的错误
FRotator NewActorRotator = FRotator(FMath::Clamp((ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)),-80.f,-10.f),
ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
SetActorRotation(NewActorRotator);
}
if (bIsMouseRightDown)
{
FVector SpeedMove = FVector(MouseVariationDifference.Y * MouseRightSpeed,
-1.0 * MouseRightSpeed * MouseVariationDifference.X, 0);
AddActorLocalOffset(SpeedMove);
//限制z轴
FVector Location = GetActorLocation();
FVector NewLocation = FVector(Location.X, Location.Y, 4520);
SetActorLocation(NewLocation);
}
}
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//获取鼠标坐标
GetMousePosition();
//鼠标移动视角
MouseMove();
}
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EnhancedInputConponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (EnhancedInputConponent)
{
EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Started, this, &AMyCharacter::LeftMouseDown);
EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::LeftMouseUp);
EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Started, this, &AMyCharacter::RightMouseDown);
EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::RightMouseUp);
EnhancedInputConponent->BindAction(MiddleButtonAction, ETriggerEvent::Triggered, this, &AMyCharacter::MiddleMouseSlide);
}
}
void AMyCharacter::GetMousePosition()
{
//获取当前鼠标移动坐标
GetWorld()->GetFirstPlayerController()->GetMousePosition(MousePos.X, MousePos.Y);
//记录的鼠标变化差量
MouseVariationDifference = MousePos - FVector2D(MouseX, MouseY);
//记录变化后的鼠标位置
MouseX = MousePos.X;
MouseY = MousePos.Y;
//打印鼠标信息到屏幕
/*GEngine->AddOnScreenDebugMessage(1, 1, FColor::Red, FString::Printf(TEXT("%f,%f"), MousePos.X, MousePos.Y));
GEngine->AddOnScreenDebugMessage(2, 1, FColor::Yellow, FString::Printf(TEXT("%f,%f"), MouseVariationDifference.X, MouseVariationDifference.Y));*/
}