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

news2024/11/29 1:04:19

根据官方文档创建一个可以控制前后左右移动、旋转视角、缩放视角的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

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

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

相关文章

多目标优化算法——多目标粒子群优化算法(MOPSO)

Handling Multiple Objectives With Particle Swarm Optimization&#xff08;多目标粒子群优化算法&#xff09; 一、摘要&#xff1a; 本文提出了一种将帕累托优势引入粒子群优化算法的方法&#xff0c;使该算法能够处理具有多个目标函数的问题。与目前其他将粒子群算法扩展…

HTML5好看的音乐播放器多种风格(附源码)

文章目录 1.设计来源1.1 音乐播放器风格1效果1.2 音乐播放器风格2效果1.3 音乐播放器风格3效果1.4 音乐播放器风格4效果1.5 音乐播放器风格5效果 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&…

通用网络安全设备之【防火墙】

概念&#xff1a; 防火墙&#xff08;Firewall&#xff09;&#xff0c;也称防护墙&#xff0c;它是一种位于内部网络与外部网络之间的网络安全防护系统&#xff0c;是一种隔离技术&#xff0c;允许或是限制传输的数据通过。 基于 TCP/IP 协议&#xff0c;主要分为主机型防火…

c++趣味编程玩转物联网:基于树莓派Pico控制有源蜂鸣器

有源蜂鸣器是一种简单高效的声音输出设备&#xff0c;广泛应用于电子报警器、玩具、计时器等领域。在本项目中&#xff0c;我们结合树莓派Pico开发板&#xff0c;通过C代码控制有源蜂鸣器发出“滴滴”声&#xff0c;并解析其中涉及的关键技术点和硬件知识。 一、项目概述 1. 项…

jar包打成exe安装包

打包exe并设置管理员权限 前言打包可执行文件exe准备jre环境运行exe4j并配置 设置执行文件exe管理员权限设置打包工具管理员权限打包exe安装包创建脚本打包 前言 准备安装包&#xff1a; jar包&#xff1a;自己的程序&#xff1b;exe4j&#xff1a;将jar打包可执行的exe&…

NAT:连接私有与公共网络的关键技术(4/10)

一、NAT 的工作原理 NAT 技术的核心功能是将私有 IP 地址转换为公有 IP 地址&#xff0c;使得内部网络中的设备能够与外部互联网通信。其工作原理主要包括私有 IP 地址到公有 IP 地址的转换、端口号映射以及会话表维护这几个步骤。 私有 IP 地址到公有 IP 地址的转换&#xff1…

多模态大型语言模型(MLLM)综述

目录 多模态大语言模型的基础 长短期网络结构(LSTM) 自注意力机制 基于Transformer架构的自然语言处理模型 多模态嵌入概述 多模态嵌入关键步骤 多模态嵌入现状 TF-IDF TF-IDF的概念 TF-IDF的计算公式 TF-IDF的主要思路 TF-IDF的案例 训练和微调多模态大语言模…

学习ASP.NET Core的身份认证(基于Cookie的身份认证3)

用户通过验证后调用HttpContext.SignInAsync函数将用户的身份信息保存在认证Cookie中,以便后续的请求可以验证用户的身份,该函数原型如下所示&#xff0c;其中properties参数的主要属性已在前篇文章中学习&#xff0c;本文学习scheme和principal的意义及用法。 public static …

C++设计模式-模板模式,Template Method

动机&#xff08;Motivation&#xff09; 在软件构建过程中&#xff0c;对于某一项任务&#xff0c;它常常有稳定的整体操作结构&#xff0c;但各个子步骤却有很多改变的需求&#xff0c;或者由于固有的原因&#xff08;比如框架与应用之间的关系&#xff09;而无法和任务的整…

Jenkins流水线 Allure JUnit5 自动化测试

目录 一、Jenkins Allure配置 1.1 安装Allure插件 1.2 安装Allure工具 1.3 配置测试报告路径 1.4 JenkinsFile 二、Jenkins 邮箱配置 2.1 安装Email Extension Plugin插件 2.2 邮箱配置 2.3 JenkinsFile 三、项目pom.xml 配置 3.1 引入allure-junit5依赖 3.2 引入m…

计算机网络 实验七 NAT配置实验

一、实验目的 通过本实验理解网络地址转换的原理和技术&#xff0c;掌握扩展NAT/NAPT设计、配置和测试。 二、实验原理 NAT配置实验的原理主要基于网络地址转换&#xff08;NAT&#xff09;技术&#xff0c;该技术用于将内部私有网络地址转换为外部公有网络地址&#xff0c;从…

shell脚本基础学习_总结篇(完结)

细致观看可以&#xff0c;访问shell脚本学习专栏&#xff0c;对应章节会有配图https://blog.csdn.net/2201_75446043/category_12833287.html?spm1001.2014.3001.5482 导语 一、shell脚本简介 1. 定义&#xff1a; 2. 主要特点&#xff1a; 3. shell脚本的基本结构 4. S…

ACL的原理与配置

ACL技术概述 ACL&#xff1b;访问控制列表 技术背景&#xff1a; 园区重要服务器资源被随意访问&#xff0c;容易泄露机密&#xff0c;造成安全隐患 病毒侵入内网&#xff0c;安全性降低 网络宽带被各类业务随意挤占&#xff0c;服务质量要求高的宽带得不到保障&#xff0…

AWS 新加坡EC2 VPS 性能、线路评测及免费注意事项

原文论坛给你更好的阅读讨论体验&#x1f490;&#xff1a; AWS 新加坡EC2 VPS 性能、线路评测及免费注意事项 - VPS - 波波论坛 引言 对于那些习惯薅“羊毛”的朋友来说&#xff0c; AWS 的 免费套餐 可能已经非常熟悉。这台vps是我用外币卡薅的免费的12个月的机器&#xf…

关于人工智能

关于人工智能 什么是人工智能 人工智能里面有智能两字&#xff0c;可不代表现在所谓的人工智能真的是智能的。 现在的人工智能是建立在学习上的&#xff0c;被称为机器学习&#xff08;machine learning&#xff09;&#xff0c;或者说是深度学习&#xff08;deep learning&…

MyBatis-缓存(一级缓存、二级缓存)

一、缓存&#xff08;Cache&#xff09; 1、定义&#xff1a;缓存是一种用于存储数据的硬件设备或存储空间&#xff08;缓存不是内存&#xff09;。 2、作用&#xff1a;减轻数据库压力&#xff0c;提高查询性能 3、实现原理&#xff1a;将从数据库中查询出来的对象/记录在使…

【Zookeeper】四,Zookeeper节点类型、通知、仲裁、会话

文章目录 Zookeeper的架构znode的版本Zookeeper的节点类型层级树状结构znode的不同类型 Zookeeper监视与通知通知的类型 Zookeeper的仲裁Zk的会话会话的生命周期 Zookeeper的架构 Zookeeper的服务器端运行两种模式&#xff1a;独立模式&#xff08;standalone&#xff09;和仲…

【mac】终端左边太长处理,自定义显示名称(terminal路径显示特别长)

1、打开终端 2、步骤 &#xff08;1&#xff09;修改~/.zshrc文件 nano ~/.zshrc&#xff08;2&#xff09;添加或修改PS1&#xff0c;我是自定义了名字为“macminiPro” export PS1"macminiPro$ "&#xff08;3&#xff09;使用 nano: Ctrl o &#xff08;字母…

macos 14.0 Monoma 修改顶部菜单栏颜色

macos 14.0 设置暗色后顶部菜单栏还维持浅色&#xff0c;与整体不协调。 修改方式如下&#xff1a;

树莓派3:64位系统串口(UART)使用问题的解决方法

前言 当我们要使用串口进行zigbee的短距离通信时,发现无法使用串口. 原因 树莓派3bCPU内部有两个串口,一个硬件串口(就是我们平时使用的UART),还有一个迷你串口(mini-uart),在老版本的树莓派中把硬件串口分配在GPIO上,可以单独使用.但是在新的树莓派中官方把硬件串口给了蓝牙…