目录
Use of custom threads 【Agendy】 :
Custom thread pool usage [Task] :
Using the built-in thread pool of ue4/5 [Abandonable] :
插件介绍
该插件制作,将从零开始,由一个空白插件一点点的制作,从写一个效果到封装,层层封装插件,简单粗暴的对插件进行了制作:
插件效果
更多的是在cpp中去使用这个插件,而不是在蓝图中,所以对于蓝图接口并没有进行一个精致的制作【有一个蓝图接口,但因为不是专门去制作的,所以这个蓝图接口实际上只能用于简单的异步加载来做一些gameinstance之类的事情,如果有需要,可以自行在里面进行添加相对应的函数。】
插件使用
如何使用这个插件,对此我在MTPLevelSubsystemBPInterface.h的底下做了注释,里面的其实是一个pawn类,只需要将里面的相应函数复制到pawn类就可以知道这是如何使用的了,不过还是简单的进行讲解:
主要的使用是分为几个大类:
自定义线程创建,简单直接创建线程:FThreadAgendyManage ThreadAgendyManage;
自定义线程池,可以往线程池内丢任务,让任务执行:FThreadTaskManageMent ThreadTaskManageMent;
从ue中的线程池内直接取线程执行:FMTPThreadAbandonableManage ThreadAbandonableManage;
协程:FMTPCoroutinesManage CoroutinesManage;
可以设置前置任务的ue线程池:FMTPThreadGraphManage GraphManage;
资源读取:FResourceLoadManage ResourceLoadManage;
使用方法是一样的,先获取他们的管理,然后使用create或者是bind,create是绑定之后直接执行异步,而bind则是创建之后挂起,由你决定使用join还是detach。
自定义线程的使用【Agendy】:
在DemoPawn中,有两个函数:
这两个函数都是自定义线程的创建,不同的是"AsynAgendyCreate"函数和"AgendyBind"函数的底层原理。
AsynAgendyCreate是创建线程绑定函数后,就直接异步进行执行。
AgendyBind是创建线程之后【函数中是直接执行,底层是将线程挂起通过join或者detach来执行【函数中用bool值来决定是用同步还是异步】】。
c++使用:
AsynAgendyCreate的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建即执行【这里做一个示例,DemoPawn中的蓝图里面是有5种绑定方式】:
GThread::GetAgendy().CreateUObject(this, &ADemoPawn::TestUObject, 777);
AgendyBind的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建后会挂起【这里做一个示例,DemoPawn中的蓝图里面是有5种绑定方式】。
前面的ThreadHandle是一个弱指针,是用于封装的一个类,详情在插件中查看:
ThreadHandle[0] = GThread::GetAgendy().BindUObject(this, &ADemoPawn::TestUObject, 777);
自定义线程池的使用【Task】:
在DemoPawn中,有两个函数:
这两个函数都是绑定任务后,向自定义的线程池中丢任务去执行,不同的是"AsynTaskCreate"函数和"TaskBind"函数的底层原理。
AsynTaskCreate是创建任务丢进线程池后,就直接异步进行执行。
TaskBind是创建任务之后【函数中是直接执行,底层是将线程挂起通过join或者detach来执行【函数中用bool值来决定是用同步还是异步】】。
c++使用:
AsynTaskCreate的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建即执行【这里做一个示例,DemoPawn中的蓝图里面是有5种绑定方式】:
GThread::GetTask().CreateUObject(this, &ADemoPawn::TestUObject, 777);
TaskBind的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建后会挂起【这里做一个示例,DemoPawn中的蓝图里面是有5种绑定方式】。
GetTask::GetTask().BindUObject(this, &ADemoPawn::TestUObject, 777);
使用ue4/5自带的线程池【Abandonable】:
在DemoPawn中,有两个函数:
这两个函数都是使用ue5内部的线程池进行执行的,不同的是"AsynAbandonableCreate"函数和"AbandonableBind"函数的底层原理。
两者都有一个InMarcoorNot:这个是决定用宏来绑定执行还是正常的使用绑定执行。
AsynAbandonableCreate是绑定任务后,通过取ue5的线程池中线程进行执行的。
AbandonableBind同样是是绑定任务之后【函数中是直接执行,底层是将任务挂起通过join或者detach来执行【函数中用bool值来决定是用同步还是异步】】。
c++使用:
AsynTaskCreate的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建即执行【这里做宏和正常的两个示例,DemoPawn中的蓝图里面是有5种绑定方式】:
ASYNCTASK_UOBJECT(this, &ADemoPawn::TestUObject, 777);
GThread::GetAbandonable().CreateUObject(this, &ADemoPawn::TestUObject, 777);
TaskBind的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建后会挂起【这里做一个示例,DemoPawn中的蓝图里面是有5种绑定方式】。
SYNCTASK_UOBJECT(this, &ADemoPawn::TestUObject, 777);
GetTask::GetAbandonable().BindUObject(this, &ADemoPawn::TestUObject, 777);
协程的使用【Coroutines】:
在DemoPawn中,有两个函数:
这两个函数都是使用协程的方法执行的,不同的是"AsynCoroutinesCreate"函数和"CoroutinesBind"函数的底层原理。
AsynCoroutinesCreate是绑定任务后,底层我用了定时器,将5个绑定的函数1秒1秒的通过唤醒的方式进行打印。
CoroutinesBind同样是是绑定任务之后【函数中是直接执行,底层是通过唤醒的方式来执行打印的】。
c++使用:
AsynCoroutinesCreate的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建即执行【这里做宏和正常的两个示例,DemoPawn中的蓝图里面是有5种绑定方式】CoroutinesHandle是一个类的数组,详情需要在底层查看:
CoroutinesHandle[0] = GThread::GetCoroutines().CreateUObject(this, &ADemoPawn::TestUObject, 777);
CoroutinesBind的底层的使用十分简单,首先是获取一下管理器,然后绑定函数,输入函数所需要的参数即可,创建后会挂起【这里做一个示例,DemoPawn中的蓝图里面是有5种绑定方式】。
GThread::GetCoroutines().BindUObject(1.0f, this, &ADemoPawn::TestUObject, 777);
资源加载的使用:
DemoPawn中有这两个函数:
同时为了更好的测试效果,添加了相应的使用方法:
逻辑:通过获取加载的资源,进行转换,获取里面的一个静态网格体,然后替换为另一个类的网格体。
两者的不同主要在上面进行了delay,因为是异步加载,所以可能导致的是在蓝图的GameThread中,你可能无法获得异步加载的资源。
而下面的是同步加载资源,所以不需要delay,能够获取加载的资源。
c++使用:
两个函数的底层是通过lambda进行实现的,通过加载资源,添加到一个数组,然后输出,在蓝图中进行转换,当然也可以在c++中就进行相应的转换。
English
How to use this plugin, I'm in MTPLevelSubsystemBPInterface. H under made a comment, it is actually a pawn class, only need to copies inside the corresponding function to pawn class can know how it is used, but is still easy to explain:
Custom thread creation, simply create a thread directly: FThreadAgendyManage ThreadAgendyManage;
To customize the thread pool, you can throw tasks into the thread pool and let the tasks execute: FThreadTaskManageMent ThreadTaskManageMent;
Take directly from ue in the thread pool thread execution: FMTPThreadAbandonableManage ThreadAbandonableManage;
Coroutine: FMTPCoroutinesManage CoroutinesManage;
You can set the ue thread pool for the preceding task: FMTPThreadGraphManage GraphManage;
Resource read :FResourceLoadManage ResourceLoadManage;
The method of using them is the same, first get their management, then use create or bind, create the async directly after binding, and bind is created and suspended, depending on whether you use join or detach.
Use of custom threads 【Agendy】 :
In DemoPawn, there are two functions:
Both of these functions are custom thread creation, the difference is the underlying principle of the "AsynAgendyCreate" and "AgendyBind" functions.
AsynAgendyCreate is a thread binding function created and executed asynchronously.
AgendyBind is created after the thread is executed directly in the function and suspended in the lower layer to execute via join or detach. The bool is used to determine whether to use synchronous or asynchronous.
c++ use:
The bottom layer of AsynAgendyCreate is very simple to use, first get a manager, and then bind the function, enter the parameters required by the function, create and execute (here is an example, the blueprint in the DemoPawn there are 5 binding methods) :
GThread::GetAgendy().CreateUObject(this, &ADemoPawn::TestUObject, 777);
To use the AgendaBind layer, it was simple to get the manager, bind the function, enter the parameters required by the function, and then suspend the creation. (As an example, the blueprint in the DemoPawn has 5 binding methods.)
The preceding ThreadHandle is a weak pointer to a class used for encapsulation, details of which can be found in the plugin:
ThreadHandle[0] = GThread::GetAgendy().BindUObject(this, &ADemoPawn::TestUObject, 777);
Custom thread pool usage [Task] :
In DemoPawn, there are two functions:
Both of these functions bind tasks and then throw tasks into the custom thread pool for execution, the difference is the underlying principle of the "AsynTaskCreate" function and the "TaskBind" function.
AsynTaskCreate means that a task is executed asynchronously after it is thrown into the thread pool.
TaskBind is created after the task is executed directly in the function, the underlying thread is suspended and executed by join or detach (the function uses a bool value to determine whether to use synchronous or asynchronous).
c++ use:
The low-level use of AsynTaskCreate is very simple, first is to get the manager, and then bind the function, enter the parameters required by the function can be created and executed [here to do an example, DemoPawn blueprint is there are 5 binding methods] :
GThread::GetTask().CreateUObject(this, &ADemoPawn::TestUObject, 777);
The underlying use of TaskBind is very simple, first get the manager, and then bind the function, enter the required parameters of the function, and then hang after creation[Here is an example, there are 5 binding methods in the blueprint of DemoPawn.].
GetTask::GetTask().BindUObject(this, &ADemoPawn::TestUObject, 777);
Using the built-in thread pool of ue4/5 [Abandonable] :
In DemoPawn, there are two functions:
Both functions are executed using ue5's internal thread pool, the difference being the underlying principles behind the "AsynAbandonableCreate" and "AbandonableBind" functions.
Both have an InMarcoorNot: this determines whether the binding is executed with a macro or normally with a binding.
AsynAbandonableCreate is a task that is bound and executed by taking threads from the ue5 thread pool.
AbandonableBind is also a abandonablebind that binds a task (which is executed directly in a function) while the underlying abandonableBind suspends the task to be executed by joining or detach (which uses a bool value to determine whether to use synchronous or asynchronous).
c++ use:
The low-level use of AsynTaskCreate is very simple, first of all to get the manager, and then bind the function, input the parameters required by the function can be created and executed [here to do macro and normal two examples, the blueprint in the DemoPawn is there are 5 binding methods] :
ASYNCTASK_UOBJECT(this, &ADemoPawn::TestUObject, 777);
GThread::GetAbandonable().CreateUObject(this, &ADemoPawn::TestUObject, 777);
The underlying use of TaskBind is very simple, first get the manager, and then bind the function, enter the required parameters of the function, and then hang after creation[Here is an example, there are 5 binding methods in the blueprint of DemoPawn.].
SYNCTASK_UOBJECT(this, &ADemoPawn::TestUObject, 777);
GetTask::GetAbandonable().BindUObject(this, &ADemoPawn::TestUObject, 777);
The use of Coroutines:
In DemoPawn, there are two functions:
Both functions are executed using coroutine methods, the difference being the underlying principle of the "AsynCoroutinesCreate" and "CoroutinesBind" functions.
AsynCoroutinesCreate is bound after the task, the bottom I use a timer, the 5 bound functions 1 second 1 second by the way to wake up to print.
CoroutinesBind is also after binding the task (the function is executed directly, the bottom layer is printed by way of wake-up).
c++ use:
The low-level use of AsynCoroutinesCreate is very simple, first of all, get the manager, and then bind the function, enter the parameters required by the function, create and execute [here do macro and normal two examples, There are 5 binding methods in the DemoPawn blueprint.
CoroutinesHandle is an array of classes.
CoroutinesHandle[0] = GThread::GetCoroutines().CreateUObject(this, &ADemoPawn::TestUObject, 777);
The underlying use of CoroutinesBind is very simple, first get the manager, and then bind the function, input the parameters required by the function can be created, and it will be suspended after creation [here is an example, there are 5 binding methods in the blueprint of DemoPawn].
GThread::GetCoroutines().BindUObject(1.0f, this, &ADemoPawn::TestUObject, 777);
Use of resource loading:
In DemoPawn, there are two functions:
At the same time, in order to better test results, the corresponding use method is added:
Logic: By getting the loaded resource, perform the transformation, get a static grid body inside, and then replace the grid body of another class.
The difference between the two is mainly due to the delay above, because it is loaded asynchronously, so it may cause that in the GameThread of the blueprint, you may not get the resources loaded asynchronously.
The following is synchronous loading resources, so there is no need to delay, can get the loaded resources.
c++ use:
The bottom layer of the two functions is implemented through lambda, by loading the resource, adding it to an array, and then output it, converting it into a blueprint, or even in c++.