UEのマルチスレッド処理（C++）

今回の方法は、こちらのYouTubeを参考にしました。

https://youtu.be/0Yyh3oQgonI
## 準備
Unreal EngineとVisual Studioのインストール
セットアップは下記のURLを参考にしてください。

https://docs.unrealengine.com/4.27/ja/ProductionPipelines/DevelopmentSetup/VisualStudioSetup/


## 方法

### Step 1 新規C++クラス
![o01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727189/92ac2e62-85e6-92ff-ea45-8be7d9e85825.png)
以下の二つクラスを作成します。（UE5バージョン）
* BlueprintFunctionLibrary
* Unreal Interface（アンリアル インターフェース）
![o02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727189/0e796a33-5007-89d6-c537-1f2eb9b9e737.png)

SourceフォルダにMyInterface.cpp、MyInterface.hとMyBlueFunctionLibrary.cpp、MyBlueFunctionLibrary.hが生成してくれます。（名前はデフォルトです。）
## 

### Step 2 ヘッダファイル（.hファイル）の編集
**MyInterface.h**
MyInterface.hの`IMyInterfaceクラス`内には一つの関数を作ります。
```MyInterface.h
public:
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Multithreaded")
        // イベント名
		void MultithreadFunction();
```
この関数MultithreadFunctionはバックグラウンド処理を行うタイミングです。
UEではEventというものです。


**MyBlueFunctionLibrary.h**
MyBlueFunctionLibrary.hの`UMyBlueprintFunctionLibraryクラス`内には一つの関数を作ります。
```MyBlueFunctionLibrary.h
public:
	UFUNCTION(BlueprintCallable, Category = "MyInterface")
        // 非同期処理を呼び関数
		static void CallMultithreadFunction(UObject* object) {
        // 非同期処理のタスクをバックグラウンドで実行
		(new FAutoDeleteAsyncTask<MultithreadedTask>(object))->StartBackgroundTask();
	}
```
この関数CallMultithreadFunctionはマルチスレッド処理を開始する関数です。
この関数を実行すると、MyInterfaceのMultithreadFunction関数を実行して、
バックグラウンド処理が始まり、マルチスレッドができます。

MyBlueFunctionLibrary.hには`MultithreadedTaskクラス`の定義も記述します。
このクラス内にはDoWork関数はMyInterfaceのMultithreadFunction関数を実行するという意味です。

```MyBlueFunctionLibrary.h
// このMultithreadedTaskクラスはタスクを定義するクラスです。

class MultithreadedTask : public FNonAbandonableTask {

public:
	UObject* object;

	MultithreadedTask(UObject* object) { this->object = object; }
    // ワーク実行
	// 非同期処理を指定された関数の実行
    void DoWork()
	{
		IMyInterface::Execute_MultithreadFunction(object);
	}

	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(MultithreadedTask, STATGROUP_ThreadPoolAsyncTasks);
	}
};

```
MyBlueFunctionLibrary.hの先頭のinclude部分にも
マルチスレッド処理用の`Async/AsyncWork.h`と`MyInterface.h`をインポートしなければなりません。
```MyBlueFunctionLibrary.h
#include "MyInterface.h"
#include "Async/AsyncWork.h"
```


## 

### Step 3 ブループリントで使う
まずはクラス設定のインターフェースで`MyInterface`を追加します。
![o04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727189/deeff19d-014d-0b0b-6faf-32a53ca73520.png)
![o03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727189/8fb38f5b-691c-311c-f740-50eb4b731886.png)

ブループリントでマルチスレッド処理をしたい頃では**CallMultithreadFunction**のノードと連結し、
バックグラウンドで処理したい部分は**MultithreadFunction**と連結します。
![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727189/244ccfd2-808c-9557-9cc2-9ac1d8880e4c.png)


## 
### 感想
今回のマルチスレッド処理はAsyncTaskのFAutoDeleteAsyncTaskクラスを使用しました。これはUEから提供しているFQueuedThreadPoolスレッドプールを使用して、タスクが完了したら、自動的にスレッドを削除することができました。
ただし、このスレッドではオブジェクトやアクターの変更ができません。

この方法以外ではFAsyncTaskというクラスもあります。自分のスレッドプールが作れて、削除のタイミングも定義できます。
マルチスレッド処理はまだ初心者なので、今後も学習すべきことがたくさんあると思います。

3DCGシステムのご検討やご相談は弊社までお問い合わせください。

https://www.i-enter.co.jp