UE5 C++ Subsystem 和 多线程

一.Subsystem先做一个简单的介绍,其实可以去看大钊的文章有一篇专门讲这个的。

GamePlay框架基础上的一个增强功能,属于GamePlay架构的范围。Subsystems是一套可以定义自动实例化和释放的类的框架。这个框架允许你从5类里选择一个来定义子类(只能在C++定义):

有点像“全局变量”,也有点像是静态蓝图函数(如GetGameInstance),可以方便的在蓝图的各个地方调用。Subsystems真正的威力其实远不止这点手头上的便利,而在于接下来要谈的引擎帮你自动处理的部分。说实话,我还没理解到这个层次上

Subsystem对象的生命周期取决于其依存的Outer对象的生命周期,随着Outer对象的创建而创建,随着Outer对象的销毁而销毁。而选择依存哪种Outer对象,就是选择哪种Subsystem生命周期,靠的就是选择继承于哪个Subsystem基类。

二.简单创建一个单例。

重写父类的父类USubsystem的这三个函数:

	virtual bool ShouldCreateSubsystem(UObject* Outer) const override;/** Implement this for initialization of instances of the system */virtual void Initialize(FSubsystemCollectionBase& Collection) override;/** Implement this for deinitialization of instances of the system */virtual void Deinitialize() override;

以此来看它的生命周期

bool UMyGameInstanceSubsystem::ShouldCreateSubsystem(UObject* Outer) const
{return true;
}void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{Super::Initialize(Collection);UE_LOG(LogTemp,Warning,TEXT("Initialize"));//myRunnable = Ins = this;
}void UMyGameInstanceSubsystem::Deinitialize()
{Super::Deinitialize();UE_LOG(LogTemp, Warning, TEXT("Deinitialize"));
}

接着重点来了,定义成单例。经典的单例写法,一个static指针,一个staic获得自己的函数。

public:static  UMyGameInstanceSubsystem* Ins;  //static 不能加反射UFUNCTION(BlueprintCallable,Category = "MyGameInstanceSubsystem")static UMyGameInstanceSubsystem* Get();

这个指针,在CPP里面,开头需要初始化空。不然会报错,因为static的指针在类对象生成之前。

然后,在这个线程初始化完成后,将这个Ins 指针指向自己。

void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{Super::Initialize(Collection);UE_LOG(LogTemp,Warning,TEXT("Initialize"));//myRunnable = Ins = this;
}

在Get()函数里,返回Ins这种指向的单例子系统。这样UFUNCTION蓝图,和C++里都能很方便获得。

UMyGameInstanceSubsystem* UMyGameInstanceSubsystem::Get()
{UE_LOG(LogTemp, Warning, TEXT("Get Subsystem"));return Ins;
}

三.在单例里面,写线程

1.先把线程类准备好,不继承UE的类,头文件如下。我觉得可以暂时理解为线程的生命周期,是由代码确定的,而不是直接和UE的其它类保持相同。

#include "CoreMinimal.h"
#include "HAL/Runnable.h" 
#include "HAL/ThreadSafeBool.h" //线程安全

创建一个空的类,在类里面继承FRunnable。类的名字也需要改为F开头。童谣需要重写FRunnable的四个函数。

class MYPROJECT_API FMyRunable:public FRunnable //
{
public:FMyRunable();~FMyRunable();FMyRunable(FString InThreadName);virtual bool Init()override;virtual uint32 Run() override;virtual void Stop() override;virtual void Exit() override;FString ThreadName;
private:bool IsRunning;
};

2.线程的实现如下

简单的输出日志

	UFUNCTION(BlueprintCallable, Category = "MyGameInstanceSubsystem")void StartThread();UFUNCTION(BlueprintCallable, Category = "MyGameInstanceSubsystem")void StopThread();


FMyRunable::FMyRunable()
{UE_LOG(LogTemp, Warning, TEXT("gouzaohanshu"));
}FMyRunable::~FMyRunable()
{UE_LOG(LogTemp, Warning, TEXT("xigouhanshu"));
}FMyRunable::FMyRunable(FString InThreadName):ThreadName(InThreadName)
{UE_LOG(LogTemp, Warning, TEXT("gouzaohanshu1"));
}bool FMyRunable::Init()
{return true;
}uint32 FMyRunable::Run()
{IsRunning = true;return uint32();
}void FMyRunable::Stop()
{IsRunning = false;
}void FMyRunable::Exit()
{UE_LOG(LogTemp, Warning, TEXT("Exit Thread"));
}

3.接着需要将子系统和线程联系起来

在GameInstance里面声明

	//TSharedPtr<MyRunable> ref;
protected:TSharedPtr<FMyRunable> myRunnable;FRunnableThread* MyRunnableThread;

在GameInstance里需要实现,开启线程。这里首先创建一个myRunable对象,其次再开启线程,并关联到这个对象。这个时候,线程对象会自动开始跑自己的Run函数,因为它被开启了。

void UMyGameInstanceSubsystem::StartThread()
{myRunnable = MakeShared<FMyRunable>(TEXT("MyRunnable"));  //创建指针MyRunnableThread = FRunnableThread::Create(myRunnable.Get(),*(myRunnable->ThreadName)); //创建线程程UE_LOG(LogTemp, Warning, TEXT("Start Thread"));
}

现在我们添加myRunable里的Run的内容,让他循环输出,每三秒一次

uint32 FMyRunable::Run()
{IsRunning = true;while (IsRunning){FPlatformProcess::Sleep(3.0);UMyGameInstanceSubsystem* Instance = UMyGameInstanceSubsystem::Get();if (Instance){UE_LOG(LogTemp, Warning, TEXT("Run Thread"));}}return uint32();
}

如果想让它停止,就在GameInstanceSubsystem里实现。

void UMyGameInstanceSubsystem::StopThread()
{if(myRunnable.IsValid()){myRunnable->Stop();}UE_LOG(LogTemp, Warning, TEXT("Stop Thread"));
}
void FMyRunable::Stop()
{IsRunning = false;
}

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

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

相关文章

Linux 添加spi-nor flash支持

1. spi-nor flash简介 在嵌入式ARM开发过程中通常会使用到spi-nor flash&#xff0c;主要用于固化u-boot镜像以支持spi方式启动系统。目前常用的spi-nor flash有gd25wq128e、w25q128等flash芯片&#xff0c;下述以gd25wq128e为例进行讲解。 2.调试通常遇到的问题 无法识别到…

C# 探险之旅:第三十七节 - 类型class之Object:万物之源的奇妙冒险

嘿&#xff0c;勇敢的探险家们&#xff01;欢迎再次踏上C#的神秘之旅。今天&#xff0c;我们将深入探索一个极其强大又无处不在的“大佬”——Object 类型。想象一下&#xff0c;它就像是C#世界里的“超级英雄祖先”&#xff0c;几乎所有的类型都得叫它一声“老祖宗”。 Objec…

LabVIEW实验站反馈控制系统

开发了一套基于LabVIEW的软X射线磁性圆二色实验站的反馈控制系统。这套系统主要用于实现对实验站高电压的精确控制&#xff0c;从而保持照射在样品上的流强稳定性&#xff0c;为分析样品吸收谱提供可靠基准&#xff0c;同时提供了易用的用户界面和强大的数据存储功能。 项目背景…

aws(学习笔记第十八课) 使用aws cdk(python)进行部署

aws(学习笔记第十八课) 使用aws cdk(python)进行部署 学习内容&#xff1a; 使用aws cdk(python)进行部署整体代码&#xff08;python的通常工程&#xff09;代码动作 1. 使用aws cdk(python)进行部署 aws cdk的整体架构 前面使用了cloudformation进行了json的aws的各种组件的…

网络基础 - TCP/IP 五层模型

文章目录 一、OSI 参考模型中各个分层的作用1、应用层2、表示层3、会话层4、传输层5、网络层6、数据链路层7、物理层 二、OSI 参考模型通信处理示例 一、OSI 参考模型中各个分层的作用 1、应用层 2、表示层 负责设备固有数据格式和网络标准数据格式间的转换 实际生活中&#…

MySQL 调优技巧|索引什么时候失效?为什么?

写在前面 优化慢SQL&#xff0c;这是在工作或者面试中都不可避免的问题。这篇文章我们就来讲讲慢SQL的优化的一些方法&#xff01; 1. 升配 最简单的一步就是升配&#xff01;&#xff01;当然在降本增效的当下&#xff0c;很难能将这种单子审批下来了&#xff01; 2. 索引…

《封装继承与多态》封装的优势

文章目录 封装在面向对象编程中的优势1. 提高代码的可读性和可维护性2. 提高代码的安全性3. 降低代码的复杂性案例举例 封装在敏捷开发和团队合作中的优势1. 促进敏捷开发2. 促进团队合作案例举例 封装在面向对象编程中的优势 封装是面向对象编程&#xff08;Object-Oriented …

YOLOv5-Backbone模块实现

YOLOv5-Backbone模块实现 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 电脑系统&#xff1a;Windows11 显卡型号&#xff1a;NVIDIA Quadro P620 语言环境&#xff1a;python 3.9.7 编译器&#xff1a…

软件需求规格说明书文档,系统需求规格说明书下载,软件工程需求规格案例模板参考(word原件)

1 范围 1.1 系统概述 1.2 文档概述 1.3 术语及缩略语 2 引用文档 3 需求 3.1 要求的状态和方式 3.2 系统能力需求 3.3 系统外部接口需求 3.3.1 管理接口 3.3.2 业务接口 3.4 系统内部接口需求 3.5 系统内部数据需求 3.6 适应性需求 3.7 安全性需求 3.8 保密性需求 3.9 环境需求…

Linux - MySQL迁移至一主一从

Linux - MySQL迁移至一主一从 迁移准备安装MySQL ibd文件迁移原服务器操作目标服务器操作 一主一从增量同步异常解决结尾 首先部分单独安装MySQL&#xff0c;请参考Linux - MySQL安装&#xff0c;迁移数据量比较大约400G左右且网络不通故使用文件迁移&#xff0c;需开启一段时间…

29. Three.js案例-自定义平面图形

29. Three.js案例-自定义平面图形 实现效果 知识点 WebGLRenderer WebGLRenderer 是 Three.js 中用于渲染 3D 场景的核心类。它利用 WebGL 技术在浏览器中渲染 3D 图形。 构造器 THREE.WebGLRenderer(parameters : object) 参数类型描述parametersobject可选参数对象&…

大模型运用-Prompt Engineering(提示工程)

什么是提示工程 提示工程 提示工程也叫指令工程&#xff0c;涉及到如何设计、优化和管理这些Prompt&#xff0c;以确保AI模型能够准确、高效地执行用户的指令&#xff0c;如&#xff1a;讲个笑话、java写个排序算法等 使用目的 1.获得具体问题的具体结果。&#xff08;如&…

MTK Android12 更换开机LOGO和开机动画

1、路径&#xff1a; &#xff08;1&#xff09;device/mediatek/system/common/device.mk &#xff08;2&#xff09;vendor/audio-logo/animation/bootanimation.zip &#xff08;3&#xff09;vendor/audio-logo/products/resource-copy.mk &#xff08;4&#xff09;vendo…

嵌入式驱动开发详解16(音频驱动开发)

文章目录 前言WM8960简介I2S协议接口说明 SAI音频接口简介驱动框架简介设备树配置内核使能声卡设置与测试 后续参考文献 前言 该专栏主要是讲解嵌入式相关的驱动开发&#xff0c;但是由于ALSA驱动框架过于复杂&#xff0c;实现音频编解码芯片的驱动不是一个人能完成的&#xf…

learn-(Uni-app)输入框u-search父子组件与input输入框(防抖与搜索触发)

1.父子组件u-search &#xff08;1&#xff09;父组件 <!-- 父组件 --> <template> <div><searchBar change"change" search"search"></searchBar> </div> </template> <script> // 子组件搜索 import…

计算机进制的介绍

一.进制介绍 对于整数&#xff0c;有四种表示方式: 1&#xff09;二进制:0,1&#xff0c;满2进1。 在golang中&#xff0c;不能直接使用二进制来表示一个整数&#xff0c;它沿用了c的特点。 参考:Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国 //赋值…

Transformers参数高效微调之LoRA

简介 LoRA: Low-Rank Adaptation of Large Language Models是微软研究人员为处理微调大语言模型的问题而引入的一项新技术。具有数十亿个参数的强大模型&#xff08;例如 GPT-3&#xff09;为了适应特定任务或领域而进行微调的成本非常高。LoRA 建议冻结预先训练的模型权重并注…

【原生js案例】如何让你的网页实现图片的按需加载

按需加载&#xff0c;这个词应该都不陌生了。我用到你的时候&#xff0c;你才出现就可以了。对于一个很多图片的网站&#xff0c;按需加载图片是优化网站性能的一个关键点。减少无效的http请求&#xff0c;提升网站加载速度。 感兴趣的可以关注下我的系列课程【webApp之h5端实…

博弈论1:拿走游戏(take-away game)

假设你和小红打赌&#xff0c;玩“拿走游戏”&#xff0c;输的人请对方吃饭.... 你们面前有21个筹码&#xff0c;放成一堆&#xff1b;每轮你或者小红可以从筹码堆中拿走1个/2个/3个&#xff1b;第一轮你先拿&#xff0c;第二轮小红拿&#xff0c;你们两个人交替进行;拿走筹码堆…

【论文阅读】IC-Light(ICLR 2025 满分论文)

Scaling In-the-Wild Training for Diffusion-based Illumination Harmonization and Editing by Imposing Consistent Light Transport 原始论文&#xff1a;https://openreview.net/pdf?idu1cQYxRI1H 补充材料&#xff1a;https://openreview.net/attachment?idu1cQYxRI1H&…