[计算机] UnrealEngine4多线程任务构建

查看:872 |回复:1 | 2021-3-31 15:39:18

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 NPC鼓励师 于 2021-3-31 15:46 编辑

这篇文章介绍了UE4中多线程任务的C++构建。

在游戏的主线程中,如果存在一个很复杂的运算,那么游戏很容易造成卡顿。在这篇文章里,我使用查找第N个质数的函数作为范例,并且分别创建了一个在游戏主进程以及新开线程中的调用。

函数构建

新建一个AActor,加入如下函数:

[代码]:
01
// Header file.

02
protected:

03

04
    /* Calculates prime numbers in the game thread */

05
    UFUNCTION(BlueprintCallable, Category = MultiThreading)

06
    void CalculatePrimeNumbers();

07

08
    /* Calculates prime numbers in a background thread */

09
    UFUNCTION(BlueprintCallable, Category = MultiThreading)

10
    void CalculatePrimeNumbersAsync();

11

12
    /* The max prime number */

13
    UPROPERTY(EditAnywhere, Category = MultiThreading)

14
    int32 MaxPrime;





新建一个FuntionLibrary,在其中加入CalculatePrimeNumbers函数,用于计算结果:

[代码]:
01
// MainFunctionLibrary.cpp

02

03
void UMainFunctionLibrary::CalculatePrimeNumbers(int32 UpperLimit)

04
{

05
    //Calculating the prime numbers...

06
    for (int32 i = 1; i <= UpperLimit; i++)

07
    {

08
        bool isPrime = true;

09
        for (int32 j = 2; j <= i / 2; j++)

10
        {

11
            if (FMath::Fmod(i, j) == 0)

12
            {

13
                isPrime = false;

14
                break;

15
            }

16
        }

17

18
        if (isPrime)

19
            GLog->Log("Prime number #" + FString::FromInt(i) + ": " + FString::FromInt(i));

20
    }

21
}





接着在Actor中添加CalculatePrimeNumbers函数:

[代码]:
1
void AMultiThreadingActor::CalculatePrimeNumbers()

2
{

3
    //Performing the prime numbers calculations in the game thread...

4
    UMainFunctionLibrary::CalculatePrimeNumbers(MaxPrime);

5
}





并且添加一个CalculatePrimeNumbersAsync函数的空实现。在编译通过之后,在Actor的继承BP中添加操作如下:

0T012A43-0.png



Task的创建

提到多线程就一定是Tasks。在这里我们创建一个在另一个线程中执行CalculatePrimeNumbers函数的类。

在这里我们需要新添加一个类继承自FNonAbandonableTask的类(可以阅读引擎源代码查看该类的详细信息)。

[代码]:
01
class PrimeCalculationAsyncTask : public FNonAbandonableTask

02
{

03
    int32 MaxPrime;

04

05
public:

06
    /*Default constructor*/

07
    PrimeCalculationAsyncTask(int32 MaxPrime)

08
    {

09
        this->MaxPrime = MaxPrime;

10
    }

11

12
    /*This function is needed from the API of the engine.

13
    My guess is that it provides necessary information

14
    about the thread that we occupy and the progress of our task*/

15
    FORCEINLINE TStatId GetStatId() const

16
    {

17
        RETURN_QUICK_DECLARE_CYCLE_STAT(PrimeCalculationAsyncTask, STATGROUP_ThreadPoolAsyncTasks);

18
    }

19

20
    /*This function is executed when we tell our task to execute*/

21
    void DoWork()

22
    {

23
        UMainFunctionLibrary::CalculatePrimeNumbers(MaxPrime);

24
    }

25
};





RETURN_QUICK_DECLARE_CYCLE_STAT宏函数就是用于处理线程池相关的信息,而DoWork函数则是进行函数的调用。

因此在这里就可以在CalculatePrimeNumbersAsync函数中来进行调用了。需要注意的是我们需要创建一个FAutoDeleteAsyncTask来进行对应的操作,它能够保证在task完成后把自己删除。

[代码]:
1
void AMultiThreadingActor::CalculatePrimeNumbersAsync()

2
{

3
    auto task = new FAutoDeleteAsyncTask<primecalculationasynctask>(MaxPrime);

4
    if (task)

5
        task -> StartBackgroundTask();

6
}</primecalculationasynctask>





如果读者想要了解更多关于UE4中的多线程操作,可以从源代码中的AsyncWork.h开始读起。





0T012A43-0.png
2021-3-31 15:39:18  
 赞 赞 0

使用道具 登录

1个回答,把该问题分享到群,邀请大神一起回答。
3#
回复 收起回复
2023-2-26 12:33:46   回复
 赞 赞 0

使用道具 登录

CG 游戏行业专业问题

技术综合程序逻辑文章算法
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表