0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Rust在虚幻引擎5中的使用

jf_wN0SrCdH 来源:Rust语言中文社区 作者:Rust语言中文社区 2022-12-21 11:05 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

前言

前段时间,研究了一套 Rust 接入 Maya Plugin 的玩法,主要原理还是使用 C ABI 去交互。那我想着 UE 是使用 C++ 写的,肯定也可以使用 C ABI 去交互,如果可以的话在 UE 中就可以使用 Rust 代码去跑,甚至还可以使用 Rust Crates,免得使用 C++ 去写关于数据库操作、加密操作等容易引发安全漏洞的代码。所以我在昨天开始了这个计划,使用了 Rust 的 html2md 的库在 UE 中使用,效果图如下。

开工

这个案例就是在 UE 中实现 html2md,虽然实际效果可能没卵用,主要目的还是带大家跑下这套流程。

我们要实现的功能就是在 Level 放置一个 Text Render
游戏开始阶段,这个
Text Render 就会拉取 Rust 官网页面,并将它转为 Markdown 格式展示在游戏中。

创建 UE 项目

我这里使用的版本是 5.0.1,大家使用 4.x 也是可以的。
我们创建一个
第三人称游戏 C++项目,命名为Html2mdExample
45f90370-807e-11ed-8abf-dac502259ad0.png

创建 UE 插件

我们将 Html2md 的功能封装成一个插件,这样就可以在各个项目中去使用它。

我们创建一个空白插件,插件名随意,我这边就叫 html2md

4619586e-807e-11ed-8abf-dac502259ad0.png

在插件中添加 Text Render

我们要在插件中添加一个 Actor,作为处理 HTTP 请求,并渲染 MarkdownText Render

一定要选择添加到插件中,而不是项目中。

4638d2fc-807e-11ed-8abf-dac502259ad0.png

TextRender.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Runtime/Engine/Classes/Components/TextRenderComponent.h"
#include "TextRender.generated.h"

UCLASS()
class HTML2MD_API ATextRender : public AActor
{
GENERATED_BODY()

UPROPERTY(VisibleAnywhere)
UTextRenderComponent* Text;

public:
ATextRender();

protected:
virtual void BeginPlay() override;

public:
virtual void Tick(float DeltaTime) override;

};

TextRender.cpp

简单写一写代码,添加一个 UTextRenderComponent,并修改它的颜色、旋转、缩放等属性。

#include "TextRender.h"

ATextRender::ATextRender()
{
PrimaryActorTick.bCanEverTick = true;

Text = CreateDefaultSubobject<UTextRenderComponent>(TEXT("Text"));
Text->SetupAttachment(RootComponent);
}

void ATextRender::BeginPlay()
{
Super::BeginPlay();

Text->SetRelativeRotation(FRotator(90.f, 180.f, 0.f));
Text->SetTextRenderColor(FColor(0, 255, 225));
Text->SetRelativeScale3D(FVector(2.f, 2.f, 2.f));
}

void ATextRender::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

}

创建 Rust 项目

我们 Rust 项目要创建在 UE 插件项目目录下。找到插件源码目录,与 C++ 源码同级运行以下命令创建项目。

cargo new --lib html2md-dylib

464fe384-807e-11ed-8abf-dac502259ad0.png

Cargo.toml

[package]
name = "html2md-dylib"
version = "0.1.0"
edition = "2021"

# 将库打包成动态链接库
[lib]
crate-type = ["dylib"]
name = "html2md_dylib"

[dependencies]
# 用于 HTML 转为 Markdown
html2md = "0.2.14"
# 用于进行 HTTP 请求
reqwest = { version = "0.11.13", features = ["blocking"] }

[build-dependencies]
# 用于生成 C 头文件
cbindgen = "0.24.3"

src/md_loader.rs

在这里我们实现一个从 HTTP 请求拉取 HTML 并转为 Markdown 的实现。

pub struct MDLoader;

impl MDLoader {
pub fn load_md_from_url(url: &str) -> String {
let body = if let Ok(res) = reqwest::get(url) {
if let Ok(text) = res.text() {
text
} else {
return format!("Failed get {} text", url);
}
} else {
return format!("Failed get {} body", url);
};

html2md::parse_html(&body)
}
}

src/lib.rs

将函数导出,这样在动态链接库中就可以调用这个函数了。

use std::{c_char, CStr, CString};

mod md_loader;

#[no_mangle]
pub extern "C" fn load_md_from_url_ffi(url: *const c_char) -> *const c_char {
let url = unsafe { CStr::from_ptr(url) };
let res = md_loader::load_md_from_url(&url.to_string_lossy());

CString::new(res).unwrap().into_raw()
}

build.rs

我们需要使用到构建脚本来帮我们生成 C 头文件,我们将在 C++ 代码中使用它。

头文件生成到 include/UEHtml2md.h

extern crate cbindgen;

use std::env;

fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let mut config: cbindgen::Config = Default::default();
config.language = cbindgen::Cxx;

cbindgen::generate_with_config(&crate_dir, config)
.expect("Unable to generate bindings")
.write_to_file("include/UEHtml2md.h");
}

html2md-dylib.build.cs

我们要添加一个 Rust 项目名.build.cs,让 UE 认到我们的动态链接库。相关文档

using System;
using System.IO;
using UnrealBuildTool;
public class Html2mdDyLib : ModuleRules
{
public Html2mdDyLib(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
if (Target.Platform == UnrealTargetPlatform.Win64)
{
// 添加头文件目录
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "include"));
// 添加 .lib
PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "target", "release", "html2md_dylib.dll.lib"));
// 添加 .dll
PublicDelayLoadDLLs.Add("html2md_dylib.dll");
// 我们需要将 .dll 文件复制到这边
RuntimeDependencies.Add("$(PluginDir)/Binaries/Win64/html2md_dylib.dll");
}
}
}

构建 Rust 项目

我们先运行构建命令

cargo build --release

然后将 html2md_dylib.dll 复制一份到 插件目录/Binaries/Win64/html2md_dylib.dll

这一步可以使用脚本去完成,我这边就不写了。

连接 Rust & UE

因为我们 Rust 项目目录名不符合 UE 的规范,所以我们要将 html2md-dylib 目录更改为 Html2mdDyLibhtml2md-dylib.build.cs 也需要更为 Html2mdDyLib.build.cs

将动态链接库添加到依赖

我们编辑 html2md.build.cs,也就是插件的构建脚本。在 PublicDependencyModuleNames 添加 Html2mdDyLibProjects

PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"Html2mdDyLib",
"Projects",
// ... add other public dependencies that you statically link with here ...
}
);

插件加载动态链接库

html2md.h

插件头文件中声明 DLL 句柄

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"

class Fhtml2mdModule : public IModuleInterface
{
void* Html2mdLibraryHandle;

public:

/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

html2md.cpp

插件加载动态链接库

如果与本案例命名不同,记得替换代码中的路径

// Copyright Epic Games, Inc. All Rights Reserved.

#include "html2md.h"
#include "Core.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"

#define LOCTEXT_NAMESPACE "Fhtml2mdModule"

void Fhtml2mdModule::StartupModule()
{
FString BaseDir = IPluginManager::Get().FindPlugin("html2md")->GetBaseDir();
FString Html2mdLibraryPath = FPaths::Combine(*BaseDir, TEXT("Binaries/Win64/html2md_dylib.dll"));
Html2mdLibraryHandle = !Html2mdLibraryPath.IsEmpty() ? FPlatformProcess::GetDllHandle(*Html2mdLibraryPath) : nullptr;

if (Html2mdLibraryHandle == nullptr)
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ThirdPartyLibraryError", "Failed to load Html2mdLibrary"));
}
}

void Fhtml2mdModule::ShutdownModule()
{
FPlatformProcess::FreeDllHandle(Html2mdLibraryHandle);
Html2mdLibraryHandle = nullptr;
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(Fhtml2mdModule, html2md)

Text Render 调用 Rust

终于来到了最后要实现的目标,我们将调用 Rust 接口,将返回值显示在 Text Render 中。

TextRender.cpp

#include "TextRender.h"
#include "Html2mdDyLib/include/UEHtml2md.h"

ATextRender::ATextRender()
{
PrimaryActorTick.bCanEverTick = true;

Text = CreateDefaultSubobject<UTextRenderComponent>(TEXT("Text"));
Text->SetupAttachment(RootComponent);
}

void ATextRender::BeginPlay()
{
Super::BeginPlay();

// 在这里调用 Rust 接口
const char* text = "https://www.rust-lang.org/";
FString result = FString(load_md_from_url_ffi(text));
Text->SetText(FText::FromString(result)); // 设置 Text 内容

Text->SetRelativeRotation(FRotator(90.f, 180.f, 0.f));
Text->SetTextRenderColor(FColor(0, 255, 225));
Text->SetRelativeScale3D(FVector(2.f, 2.f, 2.f));
}
void ATextRender::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

}

编译项目

Visual Studio虚幻引擎 中编译都可以。

在 UE 中查看效果

我们将 TextRender 拖入场景。

465ca560-807e-11ed-8abf-dac502259ad0.png

运行游戏!我们会发现 Text Render 展示了 Rust 官网的内容。

46719b64-807e-11ed-8abf-dac502259ad0.png

总结

通过这次案例,我发现 Rust 可以在 UE 中做很多事情,我只是使用了 html2md 库作为案例来演示,大家感兴趣的话也可以去使用 wsmysql 等,关于网络通讯、数据库、甚至可以在 Rust 中实现游戏功能的算法、状态机等接入到虚幻引擎中使用。
能用少量并安全的代码去编写这些复杂的功能,何乐而不为呢?

用洛佳大佬的话来说:“如果996了一整天,每个开发者都无法避免疲惫的自己忘记释放指针或者释放了两次,很有可能一个漏洞就埋下来了。

能用编程语言理论检查出来漏洞还是好事情。这也不意味着我可以做一个强行检查 C++ 的编译器来达到一样的效果,因为这种理论要求整个语言要重新设计,Rust 就是重新设计的结果”


审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    4095

    浏览量

    68722
  • 编程语言
    +关注

    关注

    10

    文章

    1966

    浏览量

    40094
  • Rust
    +关注

    关注

    1

    文章

    243

    浏览量

    7705

原文标题:Rust 在虚幻引擎 5 中的使用

文章出处:【微信号:Rust语言中文社区,微信公众号:Rust语言中文社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    光庭信息次世代HMI座舱Clutch闪耀2026北京车展

    2026北京车展光庭信息展台上,基于虚幻引擎打造的次世代HMI座舱互动体验展品——Clutch一经亮相,便成为展台焦点。Clutch是基于Unreal Engine 5最新技术架构,
    的头像 发表于 05-11 16:04 188次阅读

    纯 AI 用 Rust 写了个全新的 KiCad 兼容 EDA?但开源社区却吵翻了...

    “  聊聊一款 Rust 编写的 EDA 工具,具备现代化的 UI 并宣称原生兼容KiCad工程。但 KiCad 社区对此并不认可,觉得项目违反了 GPL 的开源协议...  ” 大家好。最近
    的头像 发表于 04-29 11:42 1208次阅读
    纯 AI 用 <b class='flag-5'>Rust</b> 写了个全新的 KiCad 兼容 EDA?但开源社区却吵翻了...

    Perforce 静态分析现已正式支持 Rust语言!

    您是否正计划通过 Rust 编程来提升内存安全性,却又担心它无法覆盖所有的安全漏洞?Perforce QAC 和 Klocwork 现在已支持分析 Rust 代码,填补了开源代码检查工具质量和治理工具链方面的空白。
    的头像 发表于 04-08 15:38 548次阅读
    Perforce 静态分析现已正式支持 <b class='flag-5'>Rust</b>语言!

    为什么 VisionFive V1 板上的 JH7100 并存 NVDLA 引擎和神经网络引擎

    我想知道为什么 VisionFive V1 板上的 JH7100 并存 NVDLA 引擎和神经网络引擎,请问?您能否举一些关于他们的用例的例子?
    发表于 03-25 06:01

    虚幻引擎5在建筑可视化的应用:趋势、挑战与基于Perforce P4的工作流程

    UE5正在重塑建筑可视化:实时交互、AI辅助、BIM联动......技术红利已来,工作流却拖了后腿?这篇干货解析了趋势和痛点,更揭秘了如何用Perforce P4打造高效的UE5工作流。
    的头像 发表于 02-27 15:26 617次阅读
    <b class='flag-5'>虚幻</b><b class='flag-5'>引擎</b><b class='flag-5'>5</b>在建筑可视化<b class='flag-5'>中</b>的应用:趋势、挑战与基于Perforce P4的工作流程

    引擎是什么?

    引擎是光通信系统的核心部件,它是一个集成化的光学子系统,负责实现光信号的收发处理,其性能对系统的信号传输有直接影响
    的头像 发表于 01-22 17:43 1922次阅读
    光<b class='flag-5'>引擎</b>是什么?

    二维影像扫描引擎门禁二维码刷卡梯控行业的应用

    在当今科技日新月异的时代,二维影像扫描引擎以其卓越的识别性能和广泛的应用领域,成为了门禁系统不可或缺的重要组成部分,尤其二维码刷卡梯控行业展现出了非凡的价值。本文将深入探讨二维影
    的头像 发表于 12-17 15:42 580次阅读
    二维影像扫描<b class='flag-5'>引擎</b><b class='flag-5'>在</b>门禁二维码刷卡梯控行业<b class='flag-5'>中</b>的应用

    2025开放原子开发者大会旋武开源社区Rust分论坛成功举办

    11月22日,2025开放原子开发者大会——旋武开源社区Rust分论坛北京顺利召开。论坛以“共建中国Rust生态”为核心主题,汇聚京东、华为、vivo、阿里、毛豆教育、DORA社区及南京大学等企业与学术机构技术专家,及众多
    的头像 发表于 11-27 14:55 926次阅读

    硬件加密引擎保障数据安全方面有哪些优势呢?

    )。 算法可配置性:部分型号支持算法动态切换,例如在跨境物联网场景,设备可根据接入网络的区域要求,通过硬件指令切换至当地合规算法(如在国内用 SM4,欧美用 AES),无需修改软件架构。 5. 简化上层
    发表于 11-17 06:47

    2025开放原子开发者大会旋武社区Rust分论坛即将启幕

    在数字化转型持续深化、系统安全与性能需求愈发迫切的当下,Rust凭借强大的内存安全、高并发性能和卓越的开发者体验,正成为重塑软件开发疆界的关键力量,更是构建下一代可靠高效基础设施的核心选择。11月
    的头像 发表于 11-13 10:00 821次阅读

    RusT-Thread:基于Rust面向资源受限嵌入式设备的操作系统的实践 | 技术集结

    RT-Thread为基础,使用Rust语言重构其内核,形成了全新的RusT-Thread系统。系统采用模块化架构,涵盖内核服务、进程调度、内存管理、线程通信与时钟控制等核心
    的头像 发表于 11-07 17:37 7178次阅读
    <b class='flag-5'>RusT</b>-Thread:基于<b class='flag-5'>Rust</b>面向资源受限嵌入式设备的操作系统的实践 | 技术集结

    光庭信息亮相2025上海虚幻引擎技术开放日

    专家与前沿科技企业,共同解锁虚幻引擎(UE)技术的未来边界。光庭信息智能座舱事业部技术总监陈治汽车峰会专场发表《虚幻引擎助力3D智能座舱从
    的头像 发表于 08-28 15:30 1545次阅读

    光庭信息邀您相约2025上海虚幻引擎技术开放日

    8月22日至23日,备受瞩目的2025上海虚幻引擎技术开放日(Unreal Fest Shanghai 2025)将在上海宝华万豪酒店隆重举行。Epic Games创始人兼CEO Tim
    的头像 发表于 08-21 16:10 1352次阅读

    RT-Thread 遇上 Rust:安全内核 RusT-Thread 的诞生

    大家好,我们是中国科学技术大学操作系统原理与设计(H)课oooooS小组。这个项目是我们的课程大作业:参考RT-Thread架构,使用Rust搭建一个原生的嵌入式操作系统内核。初识Rust是因为xk
    的头像 发表于 08-02 11:03 3845次阅读
    RT-Thread 遇上 <b class='flag-5'>Rust</b>:安全内核 <b class='flag-5'>RusT</b>-Thread 的诞生

    请问OpenVINO™ 是否支持 Rust 绑定?

    无法确定OpenVINO™是否支持 Rust 绑定。
    发表于 06-25 07:45