UE(虚幻)学习(四) 第一个C++类来控制小球移动来理解蓝图和脚本如何工作

UE5视频看了不少,但基本都是蓝图如何搞,或者改一下属性,理解UE系统现有组件使用的。一直对C++脚本和蓝图之间的关系不是很理解,看到一个视频讲的很好,我也做笔记记录一下。

我的环境是UE5.3.2.

创建UE空项目

我们创建一个空项目
在这里插入图片描述

创建类MyPlayer

进入项目后,我们直接创建一个C++类。
在这里插入图片描述
因为是从基础理解,所以就选择更基础的Pawn类,不使用Character类。
在这里插入图片描述
我起名字MyPlayer类。确定后就提示会
在这里插入图片描述
之前创建的是蓝图项目,创建类后就包含源码了,需要关闭UE重新进入。

进入后我们就可以看到自己建立的类了。
在这里插入图片描述
如果你看不到C++Classes,请掉右边的Settings,并勾选Show C++ Classes。
在这里插入图片描述
这里我重新创建了类名BallPlayer,不喜欢之前的MyPlayer的名字,就不附上截图了。

查看新生成的文件

我们用VS打开项目,可以看到.h和.cpp文件,内容如下:

BallPlayer.h

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

#pragma once

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

UCLASS()
class MYPROJECT4_API ABallPlayer : public APawn
{
	GENERATED_BODY()

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

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;

};


BallPlayer.cpp

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


#include "BallPlayer.h"

// Sets default values
ABallPlayer::ABallPlayer()
{
 	// 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;

}

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

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

}

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

}



UE的类前面自动添加了A字母。继承于APawn。

修改代码

下面我们添加一些代码:
BallPlayer.h文件中添加了三个组件:模型Mesh,弹簧,相机。
Mesh就是我们控制看到的小球(UStaticMeshComponent),弹簧(USpringArmComponent)就是用来控制相机和小球之间的距离,相机(UCameraComponent)就是我们的画面视角。

然后MoveForce和JumpForce是控制的物理力大小。

方法:
MoveRight是用来处理左右移动的
MoveForward是用来处理前后移动的
Jump是跳跃

这里注意下头文件,引用的文件要写在#include "BallPlayer.generated.h"的前面。

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

#include "BallPlayer.generated.h"


UCLASS()
class MYPROJECT4_API ABallPlayer : public APawn
{
	GENERATED_BODY()

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

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	UStaticMeshComponent* MeshMain;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	USpringArmComponent* SpringArmMain;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
	UCameraComponent* CameraMain;

	UPROPERTY(EditAnywhere,BlueprintReadWrite)
	float MoveForce = 500.00f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float JumpForce = 500.00f;

public:	
	// Called every frame
	//virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	void MoveRight(float value);
	void MoveForward(float value);
	void Jump();
};

我们再来看CPP文件
构造函数中我们看到创建了Mesh,SpringArm和Camera。
SetupAttachment的作用是设置父对象,例如SprintArm的父对象是Mesh。相机是最子层。

SetupPlayerInputComponent函数中绑定了按键,我们后面再截图上来。
BindAction,BindAxis 分别对应了不同的操作。

当键盘按下的时候,就进入(MoveRight,MoveForward,Jump)3个函数进行前后左右跳跃处理。

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


#include "BallPlayer.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"


// Sets default values
ABallPlayer::ABallPlayer()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false;
	MeshMain = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
	SpringArmMain = CreateDefaultSubobject<USpringArmComponent>("SpringArm");
	CameraMain = CreateDefaultSubobject<UCameraComponent>("Camera");

	RootComponent = MeshMain;
	SpringArmMain->SetupAttachment(MeshMain);
	CameraMain->SetupAttachment(SpringArmMain);

	MeshMain->SetSimulatePhysics(true);
	SpringArmMain->bUsePawnControlRotation = true;
}

// Called when the game starts or when spawned
void ABallPlayer::BeginPlay()
{
	Super::BeginPlay();
	MoveForce *= MeshMain->GetMass();
	JumpForce *= MeshMain->GetMass();
}

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

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

	//映射按键
	InputComponent->BindAction("Jump", IE_Pressed, this, &ABallPlayer::Jump);
	InputComponent->BindAxis("MoveForward", this,  &ABallPlayer::MoveForward);
	InputComponent->BindAxis("MoveRight", this,  &ABallPlayer::MoveRight);
}

void ABallPlayer::MoveRight(float value)
{
	const FVector right = CameraMain->GetRightVector() * MoveForce * value;
	MeshMain->AddForce(right);
}

void ABallPlayer::MoveForward(float value)
{
	const FVector forward = CameraMain->GetForwardVector() * MoveForce * value;
	MeshMain->AddForce(forward);
}

void ABallPlayer::Jump()
{
	MeshMain->AddImpulse(FVector(0, 0, JumpForce));
}


键盘的设置

我们打开菜单的编辑Edit 、项目设置Project Settings
在这里插入图片描述
代码编写好后可以按下Ctrl+Alt+F11,进行快速编译。

创建蓝图

我们的代码编译完成后,可以再脚本上右键创建蓝图。
在这里插入图片描述
或者可以再文件夹力点击右键创建蓝图:
在这里插入图片描述
在弹出界面上搜索ballplayer选择确定。
在这里插入图片描述
双击建立好的蓝图BP_BallPlayer,会进入蓝图界面,我们就看到Mesh弹簧和相机的层次结构了。
在这里插入图片描述

设置小球

蓝图里我们点击小球选择一个Mesh
在这里插入图片描述
这里选择的小球Mesh是100*100的。

设置弹簧

在这里插入图片描述
我们关闭几个参数inheritPitch等,按E切换到旋转,然后让相机有一些高度,这样视角舒服一些。

保存蓝图

最后保存蓝图,并点击Compile编译。
在这里插入图片描述

设置玩家

在场景中拖入BP_BallPlayer蓝图,并且设置Pawn里的AutoPossessPlayer的属性选择Player 0。
在这里插入图片描述

运行游戏

请添加图片描述

参考:
https://www.youtube.com/watch?v=KQgOqyYoHAs

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

细说STM32F407单片机IIC总线基础知识

目录 一、 I2C总线结构 1、I2C总线的特点 2、I2C总线通信协议 3、 STM32F407的I2C接口 二、 I2C的HAL驱动程序 1、 I2C接口的初始化 2、阻塞式数据传输 &#xff08;1&#xff09;函数HAL_I2C_IsDeviceReady() &#xff08;2&#xff09;主设备发送和接收数据 &#…

关于easy-es对时间范围查询遇到的小bug

前言&#xff1a;在使用easy-es之前作为一个小白的我只有es原生查询的基础&#xff0c;在自己通过查看官方文档自学easy-es遇到了一个挫折&#xff0c;其他的还好语法和MybatisPlus差不多&#xff0c;正以为我觉得很快就能入手&#xff0c;在对时间范围的判断就给我当头一棒&am…

Flink源码解析之:如何根据算法生成StreamGraph过程

Flink源码解析之&#xff1a;如何根据算法生成StreamGraph过程 在我们日常编写Flink应用的时候&#xff0c;会首先创建一个StreamExecutionEnvironment.getExecutionEnvironment()对象&#xff0c;在添加一些自定义处理算子后&#xff0c;会调用env.execute来执行定义好的Flin…

【代码随想录|完全背包问题】

518.零钱兑换|| 题目链接&#xff1a;518. 零钱兑换 II - 力扣&#xff08;LeetCode&#xff09; 这里求的是组合数&#xff0c;就是不强调元素排列的顺序&#xff0c;211和121是同一个数那种&#xff0c;要先遍历物品&#xff0c;这样的话我算出来的每个值才是按顺序121&…

一款汽车连接器(HSD(4+2))信号完整性仿真

下面是一款汽车连接器HSD(42) 的3D外形&#xff1a; 其爆炸图如下&#xff1a; 下面是Rosenboger同款产品的2D图&#xff1a; 其信号完整性参数如下&#xff1a; 下面介绍一下如何给上面的3D模型做信号完整性仿真。 在介绍仿真前先介绍一下上面的一些参数&#xff1a;上面的参数…

安卓/system/bin下命令中文说明(AI)

ATFWD-daemon&#xff1a;AT指令转发守护进程&#xff0c;用于将AT指令从应用层转发到调制解调器。 PktRspTest&#xff1a;数据包响应测试工具。 StoreKeybox&#xff1a;存储密钥盒工具&#xff0c;用于安全地存储加密密钥。 WifiLogger_app&#xff1a;WiFi日志记录应用&…

华为开源自研AI框架昇思MindSpore应用案例:ICNet用于实时的语义分割

ICNet用于实时的语义分割 ICNet 被广泛应用于实时的语义分割领域。它在处理图像数据时&#xff0c;能够以较高的效率进行语义分割操作&#xff0c;为相关领域的研究和实际应用提供了有力的支持。ICNet 的实时性使其在众多场景中都具有很大的优势&#xff0c;例如在视频处理、自…

docker-compose搭建sfpt服务器

1. 搭建 创建sftp目录&#xff0c;进入该目录创建docker-compose.yml文件内容如下&#xff1a; version: 3.7services:sftp:image: atmoz/sftpcontainer_name: sftpports:- "122:22"volumes:- ./sftp-data:/homeenvironment:SFTP_USERS: "liubei:liubei161:10…

跨域请求问题

跨域请求简介 跨域请求&#xff1a;通过一个域的JavaScript脚本和另外一个域的内容进行交互 域的信息&#xff1a;协议、域名、端口号 同域&#xff1a;当两个域的协议、域名、端口号均相同 如下所示&#xff1a; 同源【域】策略&#xff1a;在浏览器中存在一种安全策略就是…

AI发展新态势:从技术突破到安全隐忧

AI安全的新挑战 近期AI领域出现了令人担忧的新发现。根据最新研究,AI模型已经开始展现出策略性欺骗的倾向。具体表现在以下几个方面: 策略性欺骗行为的出现 在实验中发现,当研究人员试图让AI执行一些"反Anthropic"的操作时(如获取模型权限和外部服务器访问),模…

【学生管理系统】环境搭建

目录 1. 环境搭建 1.1 前端环境 1.2 后端环境 1.2.1 父项目 1.2.2 domain项目 1.2.3 gateway项目 1.3 数据库环境 1.3.1 用户数据库 1.3.2 班级数据库 1.3.3 学生数据库 1.3.4 课程数据库 1. 环境搭建 1.1 前端环境 项目名&#xff1a;nacos-nuxt-student-fore 创…

若依数据权限控制

效果 新建用户 表结构 sys_role_dept 这张表的存在。是为了实现数据权限自定义的功能 service层 mapper层 流程

vue源码分析(十)—— 生命周期

文章目录 前言一、关键方法 callHook二、详细的钩子函数说明1.beforeCreate和create2.beforeMount & mounted注意点组件&#xff08;非根组件&#xff09;的渲染节点&#xff08;1&#xff09;invokeInsertHook函数&#xff08;2&#xff09;insert方法&#xff08;3&#…

【运维】部署MKDocs

部署MKDocs obsidian 记录笔记&#xff0c;通过 mkdocs 私有化部署。 1 使用MKDocs创建笔记 创建仓库&#xff0c;安装 Material for MkDocs 和 mkdocs-minify-plugin mkdir tmp cd tmp git initpip install mkdocs-material pip install mkdocs-minify-pluginmkdocs new .2 …

深度学习——神经网络中前向传播、反向传播与梯度计算原理

一、前向传播 1.1 概念 神经网络的前向传播&#xff08;Forward Propagation&#xff09;就像是一个数据处理的流水线。从输入层开始&#xff0c;按照网络的层次结构&#xff0c;每一层的神经元接收上一层神经元的输出作为自己的输入&#xff0c;经过线性变换&#xff08;加权…

面试突击-JAVA集合类(持续更新...)

前言 这篇文档非常适合面试突击人群&#xff0c;java集合类是面试高频问点&#xff0c;阅读完此文章可以直接应对面试官一切问题&#xff0c;最终吊打面试官。 概览 Java 集合&#xff0c;也叫作容器&#xff0c;主要是由两大接口派生而来&#xff1a;一个是 Collection接口&am…

Ps:创建数据驱动的图形 - 数据组

在 Photoshop 的“变量” Variables对话框中&#xff0c;可以为某一图层定义&#xff08;或关联&#xff09;变量并指定变量类型和变量值。 请参阅&#xff1a; 《Ps&#xff1a;创建数据驱动的图形 - 定义变量》 每个实例的变量值的集合构成一个数据组 Data Set。在相应的数据…

小猫可以吃面包吗?

在宠物饲养日益普及的当下&#xff0c;小猫的饮食健康成为众多铲屎官关注的焦点。其中&#xff0c;小猫是否可以吃面包这一问题引发了不少讨论。 从面包的成分来看&#xff0c;其主要原料是面粉、水、酵母和盐&#xff0c;部分还会添加糖、油脂、鸡蛋、牛奶等。面粉富含碳水化…

OSI七层模型和交换机

概念讲解 OSI&#xff08;Open System Interconnection&#xff0c;开放系统互连&#xff09;七层模型是一种网络通信的参考模型&#xff0c;它将网络通信的功能分为七个层次&#xff0c;每个层次负责特定的任务。 七层模型记忆口诀&#xff1a;物&#xff08;物理层&#xf…

算法题(19):多数元素

审题&#xff1a; 数组不为空且一定存在众数。需要返回众数的数值 思路&#xff1a; 方法一&#xff1a;哈希映射 先用哈希映射去存储对应数据出现的次数&#xff0c;然后遍历找到众数并输出 当然也可以在第一次映射的过程中就维护一个出现次数最多的数据&#xff0c;这样子就可…