UE5-C++入门教程(二)---编写Editor类别的自定义模型实现小球规划路线的可视化

news2024/11/15 15:29:03

前言

  • 本教程将以图文教程的形式讲述如何快速入门通过C++使用UE5.4进行项目编写。
  • UE5的教程系列
    • 第一期:UE5-C++入门教程(一):使用代码创建一个指定目标的移动小球-CSDN博客
  • UE5与ROS2实战->基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(一)—UnrealCV获取深度+分割图像-CSDN博客
  • 本系列教程默认读者有C++使用基础,故不对一些C++基础知识进行详细讲解
  • 本系列教程使用的是最新的UE5.4.3VS2022作为使用实例
  • 关于本节:上一节我们介绍了如何创建Actor及其Component,并使用自定义MoveComponent完成了制定目标小球的追踪和速度设置,由于每次运行我们都需要开始仿真且需要反复进行编译整个项目,这往往是非常浪费时间和资源的,本节我们引入模型和Editor的概念,在不需要启用仿真和编译整个项目的前提下,我们完成在Editor模型下编写自定义可视化小球运动方向模型

1.基本概念:模板和插件

  • *Modules(模块): 在Unreal Engine中,模块是引擎功能的基本构建块。每个模块封装了一组相关的功能,如渲染、物理、动画、音频等。模块可以是系统级别的,也可以是项目级别的。系统级别的模块通常是引擎的一部分,而项目级别的模块则专门为特定项目定制。

    • 模块可以包含C++源代码、头文件、蓝图文件、配置文件、资源文件等。开发者可以通过添加、修改或删除模块来定制Unreal Engine的功能。模块的这种结构允许开发者只包含他们项目所需的组件,从而优化性能和资源使用。
    • 上次教程我们创建的UE5Turtorial项目就是一个Module请添加图片描述
  • *Plugins(插件): 插件是Unreal Engine中的一个特殊类型的模块,它允许开发者在不修改引擎源代码的情况下添加或扩展功能。插件可以是Epic Games提供的,也可以是第三方开发者创建的。插件通常包含一个或多个模块,它们被打包在一起,可以轻松地在不同的项目之间共享。

    • 插件可以提供从视觉效果到游戏逻辑的各种功能。开发者可以通过Unreal Engine的插件市场下载和安装插件,也可以创建自己的插件并将其分享给其他人。

2.创建自定义模块

2-1 为项目介绍模块–修改.uproject
  • 由于反复进退ue5并且进行重复编译调试连接很麻烦,这里提出一个书写自定义模块的方式,下面我们来不借助编译器和UE5,手动为项目添加一个模块

  • 这里我们随便使用一个编辑器打开你的项目根目录,这里我使用的是VScode

  • 找到项目工程文件夹Source文件夹下你的项目模块,找到你项目的.uproject文件请添加图片描述

  • 找到模组

    • Type用于指定模型的类型,这里介绍两种今天我们会用上的
      • Runtime Module运行时模块是在游戏运行时加载的模块,它们包含游戏逻辑、游戏模式、关卡脚本等。这些模块在游戏启动时加载,并在游戏运行期间保持活动状态。
      • Editor Module:编辑器模块是专门为Unreal Engine编辑器设计的模块,它们包含编辑器工具、自定义资产类型、编辑器扩展等。这些模块只在编辑器中加载和使用。
    • LoadingPhase定义了模块加载的时机。
      • Default:这是默认的加载阶段,模块在引擎初始化后加载。
      • PreLoadingScreen:模块在加载屏幕显示之前加载,通常用于初始化需要快速完成的任务。
      • PostEngineInit:模块在引擎初始化完成后加载,通常用于执行需要引擎完全初始化后才能进行的任务。
"Modules": [
	{
		"Name": "UE5Tutorial",
		"Type": "Runtime",
		"LoadingPhase": "Default",
		"AdditionalDependencies": [
			"Engine"
		]
	}
],
  • 创建一个自定义模组,设定为Editor
{
	"Name": "UE5TutorialEditor",
	"Type": "Editor",
	"LoadingPhase": "PostEngineInit"
}

2-2 为模块添加到编译组中
  • 然后找到Source目录下的.Target.cs文件,添加我们新的模块"UE5TutorialEditor.Target.cs"
// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;
using System.Collections.Generic;

public class UE5TutorialEditorTarget : TargetRules
{
	public UE5TutorialEditorTarget( TargetInfo Target) : base(Target)
	{
		Type = TargetType.Editor;
		DefaultBuildSettings = BuildSettingsVersion.V5;
		IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_4;
		ExtraModuleNames.Add("UE5Tutorial");
	}
}
  • 添加我们的新模块
//ExtraModuleNames.Add("UE5Tutorial");
ExtraModuleNames.AddRange(new string[] { "UE5Tutorial", "UE5TutorialEditor" });

  • 紧接着我们为新的模块创建一个新的文件夹,注意需要和模块名同名UE5TutorialEditor,并把我们原本项目文件夹下的UE5Tutorial.Build.cs拷贝一份到新的自定义模块的文件夹下,并改名为UE5TutorialEditor.Build.cs请添加图片描述

  • 然后我们打开UE5TutorialEditor.Build.cs,把里头对应的类名修改,并将"UnrealEd","UE5Tutorial"添加至依赖中

    • "UnrealEd" 模块指的是Unreal Engine的编辑器模块。
    • "UE5Tutorial"模块是我们上一节写的移动小球的模块
// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class UE5TutorialEditor : ModuleRules
{
	public UE5TutorialEditor(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput","UnrealEd","UE5Tutorial"});

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
		
		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}

2-3 实现模块类–继承自IModuleInterface
  • IModuleInterface 是一个接口,它定义了一个模块与其他模块或系统交互的标准方式。这个接口允许模块提供一组功能,这些功能可以在模块被加载后由其他模块调用,而不需要直接引用模块的内部实现。

  • IModuleInterface 的主要目的是为了实现模块之间的解耦,使得模块可以独立地开发、测试和更新,同时仍然能够与其他模块进行交互。通过实现 IModuleInterface,一个模块可以公开一组函数,这些函数可以被其他模块在需要时调用。

  • 我们创建如下两个文件
    请添加图片描述

  • UE5TutorialEditor.hpp

#pragma once

#include "Engine.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#include "UnrealEd.h"

DECLARE_LOG_CATEGORY_EXTERN(UE5TutorialEditor,All,All)

class FUE5TutorialEditorModule:public IModuleInterface
{
//public:
	//virtual void StartupModule()override;
	//virtual void ShutdownModule()override;
};
  • UE5TutorialEditor.cpp
#include "UE5TutorialEditor.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"

#include "UnrealEd.h"


IMPLEMENT_GAME_MODULE(FUE5TutorialEditorModule, UE5TutorialEditor);

2-4 编译
  • 回到VS2022,点击绿色透明箭头,开始构建项目,我们会发现代码新的模块的库被创建请添加图片描述

  • 在新开的UE中刷新VS2022请添加图片描述

  • VS2022就有新的模块被添加进来了请添加图片描述

  • 如果有报错,请检查代码拼写,不要漏掉了;或者拼错了函数


2-5 检查

  • 在菜单栏的工具找到调试选择模块请添加图片描述

  • 可以看到我们的模块已经被添加进来请添加图片描述


3.创建自定义可视化UI的ComponentVisualizer

  • 工具里我们新建一个C++类(具体方式上一节我们讲过,这里快速略过)
3-1 创建可视化类
  • 我们创建一个Empty的FMoveComponentVisualizer类,继承自FComponentVisualizer

    • FComponentVisualizer 是 Unreal Engine (UE) 中的一个类,它用于在 UE 编辑器中可视化场景中的组件。组件(Components)是 UE 中的一个核心概念,代表游戏对象(Actors)上的各种功能,如静态网格、骨骼网格、相机、灯光等。
    • FComponentVisualizer 类用于在编辑器中绘制组件的可视表示,这通常包括组件的边界框、碰撞体、骨骼等。开发人员可以使用这个类来创建自定义的可视化效果,以便更好地理解组件在场景中的位置和方向。
  • 这里我们实现基类的虚函数DrawVisualization请添加图片描述

    • const UActorComponent* Component: 指向要绘制的组件的指针。这是一个常量指针,意味着你不会在这个函数中修改组件的状态。
    • const FSceneView* View: 指向当前场景视图的指针。场景视图包含了渲染场景所需的所有信息,如相机设置、视口大小等。这也是一个常量指针。
    • FPrimitiveDrawInterface* PDI: 指向用于绘制原语(primitives)的接口的指针。原语可以是线、点、三角形等,用于在 3D 空间中绘制形状。通过这个接口,你可以添加自定义的绘制调用到场景中。
  • FMoveComponentVisualizer.hpp

// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "ComponentVisualizer.h"
#include "UE5Tutorial/MoveComponent.h"
/**
 * 
 */
class UE5TUTORIALEDITOR_API FMoveComponentVisualizer: public FComponentVisualizer
{
public:
	void DrawVisualization(const UActorComponent* Component,const FSceneView*View,FPrimitiveDrawInterface* PDI )override;
};
  • FMoveComponentVisualizer.cpp
    • 这里我们获取UMoveComponent,如果存在,我们就绘制一条线,起点和终点分别是小球的起点和终点
// Fill out your copyright notice in the Description page of Project Settings.


#include "MoveComponentVisualizer.h"

void FMoveComponentVisualizer::DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI)
{
	const UMoveComponent* MoveComponent = Cast<UMoveComponent>(Component);
	if (MoveComponent)
	{
		PDI->DrawLine(
			MoveComponent->StartRelativeLocation,
			MoveComponent->EndRelativeLocation,
			FLinearColor::Red,
			SDPG_Foreground,
			5.0f
			);
	}
}
  • 由于小球的StartRelativeLocationEndRelativeLocation属性是private的,这里我们需要为UMoveComponent添加友元FMoveComponentVisualizer,打开MoveComponent.cpp,添加友元
private:
	friend class FMoveComponentVisualizer;
	FVector StartRelativeLocation;
	UPROPERTY(EditAnywhere)
	float speed=1.0f;
	UPROPERTY(EditAnywhere)
	FVector EndRelativeLocation;
	FVector CurrentLocation;
	float stoppingDistance = 1.0f;
3-2 注册模型编辑可视化
  • 我们需要在编辑器中注册和注销一个自定义的组件可视化器 FMoveComponentVisualizer
  • UE5TutorialEditorModule.hpp
#pragma once

#include "Engine.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#include "UnrealEd.h"

#include "MoveComponentVisualizer.h"
DECLARE_LOG_CATEGORY_EXTERN(UE5TutorialEditor,All,All)

class FUE5TutorialEditorModule:public IModuleInterface
{
public:
	void StartupModule()override;
	void ShutdownModule()override;
};
  • UE5TutorialEditorModule.cpp
    • 首先检查 GUnrealEd(全局编辑器指针)是否有效。
    • 如果有效,它会创建一个新的 FMoveComponentVisualizer 实例,并使用 MakeShareable 函数将其转换为共享指针。
    • 它注册这个可视化器,以便它可以在编辑器中用于 UMoveComponent 类型的组件。
#include "UE5TutorialEditor.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"

#include "UnrealEd.h"


IMPLEMENT_GAME_MODULE(FUE5TutorialEditorModule, UE5TutorialEditor);
void FUE5TutorialEditorModule::StartupModule()
{
	if (GUnrealEd)
	{
		TSharedPtr<FMoveComponentVisualizer> MoveVisualizer = MakeShareable(new FMoveComponentVisualizer);
		if (MoveVisualizer.IsValid())
		{
			GUnrealEd->RegisterComponentVisualizer(UMoveComponent::StaticClass()->GetFName(), MoveVisualizer);
			MoveVisualizer->OnRegister();
		}

	}

}
void FUE5TutorialEditorModule::ShutdownModule()
{
	if (GUnrealEd)
	{
		GUnrealEd->UnregisterComponentVisualizer(UMoveComponent::StaticClass()->GetFName());


	}

}
3-3 编译
  • 我们在调试的模块中找到我们的模块,点击重新编译请添加图片描述

  • 点开输出日志,不出意料的报错了,根据报错提示请添加图片描述

  • 我们关闭实时代码编译请添加图片描述

  • 重新点击重新编译请添加图片描述


4. 结果展示

  • 我们修改Move组件的目标位置,可以发现线也随之改变请添加图片描述

  • 请添加图片描述

  • 值得一提的是,整个过程中我们不需要编译整个项目,也不需要进行仿真,这为我们进行代码调试时非常方便的。

  • 此外这条调试线将在开始仿真的时候会消失,因为这是供我们编译模型下使用,后续我们会介绍如何在运行过程中可视化


小结

  • 本节我们介绍了如何自定义module,并添加了一个Editor的模型,使我们可以在不编译整个项目不开启仿真的前提下可视化小球的规划路线。
  • 感谢大家对本教程的支持,如有错误,欢迎指出。

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

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

相关文章

MoneyPrinterTurbo的部署,在服务器Ubuntu22.04系统下——点动科技

在服务器Ubuntu22.04系统下&#xff0c;MoneyPrinterTurbo的部署 一、ubuntu22.04基本环境配置1.1 更换清华Ubuntu镜像源1.2 更新包列表&#xff1a;2. 安装英伟达显卡驱动2.1 使用wget在命令行下载驱动包2.2 更新软件列表和安装必要软件、依赖2.2 卸载原有驱动2.3 安装驱动2.4…

Axure高端交互元件库:助力产品与设计

用户体验&#xff08;UX&#xff09;和用户界面&#xff08;UI&#xff09;设计对于任何产品的成功都至关重要。为了在这个竞争激烈的市场中脱颖而出&#xff0c;设计师和产品开发团队需要依赖强大的工具来创造引人注目且功能丰富的交互界面。下面介绍一款Axure精心制作的"…

物联网(IoT)详解

物联网&#xff08;IoT&#xff09;详解 1. IoT定义简介2. IoT工作原理3. IoT关键技术4. 物联网与互联网区别5. IoT使用场景6. 开源物联网平台7. 参考资料 1. IoT定义简介 首先第一个问题&#xff0c;什么是物联网&#xff08;IoT&#xff09;? 物联网&#xff08;英文&#…

Linux:CentOS配置

一&#xff0c;安装VMware 这个可以通过官网获取 vmware下载 也可以联系我&#xff0c;我发给你 二&#xff0c;安装CentOS Centos官网找要下载的版本&#xff1a; https://vault.centos.org/ 阿里云镜像&#xff1a;https://mirrors.aliyun.com/centos-vault/?spma2c6h.13…

如何搭建redis哨兵集群

1. 构建redis镜像 FROM redis:7.0.15-alpine3.20# install tools RUN apk add curl --no-cache &&\apk add bash --no-cache # COPY redis.conf /usr/local/etc/redis/redis.confCMD [ "redis-server", "/usr/local/etc/redis/redis.conf"] dock…

一起学习LeetCode热题100道(45/100)

45.二叉树的右视图(学习) 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 …

【微信小程序】自定义组件 - 数据、方法和属性

1. data 数据 2. methods 方法 在小程序组件中&#xff0c;事件处理函数和自定义方法需要定义到 methods 节点中&#xff0c;示例代码如下&#xff1a; 3. properties 属性 在小程序组件中&#xff0c;properties 是组件的对外属性&#xff0c;用来接收外界传递到组件中的数…

如何使用docker打包后端项目并部署到阿里云k8s集群上

如何使用docker打包后端项目并部署到阿里云k8s集群上 1. 引言 在现代软件开发中,容器化技术已经成为主流,而Kubernetes (K8s) 是管理容器的首选平台之一。本文将详细介绍如何将一个后端项目使用Docker打包,并将其部署到阿里云的Kubernetes集群上。 2. 前置条件 阿里云账号…

sentinel集成springcloud实现限流熔断

Sentinel 是由阿里巴巴开源的一款流量控制和熔断降级组件,旨在通过灵活的流量控制和熔断降级机制,帮助开发者保护微服务架构中的应用和服务。 官网&#xff1a;home | Sentinel (sentinelguard.io) 一、安装sentinel 1.方式一&#xff1a;用docker-compose 安装 docker-com…

回归预测|基于粒子群优化深度神经网络DNN的数据回归预测Python程序PSO-DNN 多特征输入单输出

回归预测|基于粒子群优化深度神经网络DNN的数据回归预测Python程序PSO-DNN 多特征输入单输出 文章目录 前言回归预测|基于粒子群优化深度神经网络DNN的数据回归预测Python程序PSO-DNN 多特征输入单输出 一、PSO-DNN模型1. 粒子群优化&#xff08;PSO&#xff09;简介2. 深度神经…

java版知识付费saas租户平台的核心功能设计:打造高效、个性化的学习体验

随着互联网技术的飞速发展&#xff0c;我国在线教育行业迎来了新的变革&#xff0c;知识付费平台应运而生。这种新兴的在线教育模式&#xff0c;以用户需求为导向&#xff0c;以优质内容为核心&#xff0c;通过互联网技术手段&#xff0c;为用户提供便捷、高效的学习渠道。知识…

基于PyTorch的MNIST手写数字GAN生成器

文章目录 前言小笔记关键特性技术栈使用场景贡献者&#xff1a; 完整代码代码解析1. 导入必要的库2. 设备配置3. 超参数设置4. 创建样本目录5. 图像处理6. 加载MNIST数据集7. 创建数据加载器8. 定义判别器&#xff08;Discriminator&#xff09;D9. 定义生成器&#xff08;Gene…

C语言(15)——顺序表的应用

目录 1.基于动态顺序表实现通讯录项⽬ 1.1功能要求 1.2代码实现 2. 顺序表经典算法 1.基于动态顺序表实现通讯录项⽬ 1.1功能要求 1&#xff09;⾄少能够存储100个⼈的通讯信息 2&#xff09;能够保存⽤⼾信息&#xff1a;名字、性别、年龄、电话、地址等 3&#xff09;…

生活垃圾填埋场污染监测:新标准下的技术革新与环境保护

随着城市化进程的加速&#xff0c;生活垃圾产生量急剧增加&#xff0c;如何有效处理并控制其带来的环境污染成为亟待解决的问题。近日&#xff0c;生态环境部发布了新修订的《生活垃圾填埋场污染控制标准》&#xff08;GB 16889-2024&#xff09;&#xff0c;将自2024年9月1日起…

【Redis】哈希类型详解及缓存方式对比:从命令操作到实际应用场景

目录 Hash 哈希命令命令⼩结内部编码使⽤场景缓存方式对比 Hash 哈希 ⼏乎所有的主流编程语⾔都提供了哈希&#xff08;hash&#xff09;类型&#xff0c;它们的叫法可能是哈希、字典、关联数组、映射。在 Redis 中&#xff0c;哈希类型是指值本身又是⼀个键值对结构&#xff…

万维网与HTTP协议:基础知识简明指南

引言 在当今的数字时代&#xff0c;了解万维网&#xff08;World Wide Web, WWW&#xff09;和HTTP协议&#xff08;Hyper Text Transfer Protocol&#xff09;是至关重要的。本文将为基础小白们简明扼要地介绍万维网及其核心协议HTTP&#xff0c;并通过简单的例子和清晰的段落…

三级_网络技术_34_网络管理技术

1.在某主机上用浏览器无法访问到域名为www.tipu.edu.cn的网站&#xff0c;并且在该主机上执行tracert命令时有如下信息 分析以上信息&#xff0c;会造成这种现象的原因是 相关路由器上进行了访问控制 服务器 wwww.tjipu.edu.cn工作不正常 该计算机设置的DNS服务器工作不正常…

知行科技半年报显示商业化进展提速,下一个亮点在出海?

中国智驾落地竞速比拼愈演愈烈&#xff0c;让智驾公司陷入颇为紧张的竞争氛围。然而烈火出真金&#xff0c;这场角逐也成为领先企业脱颖而出的机会。 8月16日晚&#xff0c;智驾解决方案提供商知行科技(HK:01274)发布2024年上半年财报。数据显示&#xff0c;知行科技维持了营收…

SPI驱动学习一(协议原理)

目录 一、SPI协议介绍1. SPI 协议概述2. SPI 总线的主要组成部分3. SPI 协议的工作原理3. SPI 通信模式 二、SPI 协议的优点与缺点三、应用实例与常见问题1. 常用外设设备2. 常见问题3. 同时上电问题详细分析可能的原因解决方案 一、SPI协议介绍 1. SPI 协议概述 SPI&#xff…

【DP动态规划】学习笔记大全

-------------------------------------------------------本篇文章尚未完结&#xff0c;大家可以先看已有部分------------------------------------------------------- 【DP动态规划】学习笔记大全 Part 1 背包DP1.1 01背包1.1.1 题意解释1.1.2 为什么不使用贪心1.1.3 该如何…