【UE5.3】glTFRuntimeでロード完了通知を設定する

## 初めに
UE5.2以前でDatasmithRuntimeプラグインを用いてglb/gltfのファイルをランタイムでロードしていた方、glTFRuntimeプラグインを使ってglb/gltfのファイルをランタイムでロードしようとしている方向けの記事となっております。

UE5.2以前ですとDatasmithRuntimeプラグインを有効にすることでglb/gltfファイルをランタイムでロードすることが可能でした。DatasmithRuntime自体はUE5.3でも使用することができますが、なんとUE5.3になってからはglb/gltfファイル形式がサポートされなくなってしまいました。
一応[Interchange](https://docs.unrealengine.com/5.2/ja/importing-assets-using-interchange-in-unreal-engine/)を使って読み込むことは可能みたいですが、少し触ってみた感じ非同期で実行できていないので重いモデルなどを読み込んだ時に操作が固まるなどの問題がありそうでした（解決方法はあるかもです）。

そこで他に何か使えそうなプラグインはないか探してみたところ、マーケットプレイス内で[glTFRuntimeプラグイン](https://www.unrealengine.com/marketplace/ja/product/gltfruntime)(投稿時有料)を見つけました。
非同期でロードしたり、アニメーションの有無や、コリジョンの設定など様々な設定ができます。
基本的な使用方法は[公式ドキュメント](https://github.com/rdeioris/glTFRuntime-docs/blob/master/README.md)でまとまっています。
使い方が分からない部分に関しては[Discord](https://discord.gg/DzS7MHy)で聞くと早く回答してもらえます。

## 環境情報
Windows 11
UE 5.3.2
glTFRuntimeバージョン：20231127

## ロード完了通知の設定方法
色々と便利な機能が備わっているglTFRuntimeプラグイン。使う上で一番うれしかったのはやはり非同期でファイルのロードができることでした。
ただ、なぜか非同期のロードの完了通知がデフォルトでは行えていません。
正確な言い方をするとロード完了時に呼び出す関数自体はあるが中身が実装されていないので、継承したクラスの方で実装する前提の作りになっていそうです。

ロードが完了した時に最終的に呼び出されるのはAglTFRuntimeAssetActorAsyncクラスのReceiveOnScenesLoaded関数です。

```C++:glTFRuntimeAssetActorAsync.cpp

void AglTFRuntimeAssetActorAsync::ScenesLoaded()
{
	if (!bShowWhileLoading)
	{
		for (const TPair<UStaticMeshComponent*, UStaticMesh*>& Pair : DiscoveredStaticMeshComponents)
		{
			Pair.Key->SetStaticMesh(Pair.Value);
		}

		for (const TPair<USkeletalMeshComponent*, USkeletalMesh*>& Pair : DiscoveredSkeletalMeshComponents)
		{
			Pair.Key->SetSkeletalMesh(Pair.Value);
		}
	}

	for (TPair<USceneComponent*, FName>& Pair : SocketMapping)
	{
		for (const TPair<USkeletalMeshComponent*, USkeletalMesh*>& MeshPair : DiscoveredSkeletalMeshComponents)
		{
			if (MeshPair.Key->DoesSocketExist(Pair.Value))
			{
				Pair.Key->AttachToComponent(MeshPair.Key, FAttachmentTransformRules::KeepRelativeTransform, Pair.Value);
				Pair.Key->SetRelativeTransform(FTransform::Identity);
				break;
			}
		}
	}

	UE_LOG(LogGLTFRuntime, Log, TEXT("Asset loaded asynchronously in %f seconds"), FPlatformTime::Seconds() - LoadingStartTime);

    // 関数の呼び出し
	ReceiveOnScenesLoaded();
}

// ロード完了時に最終的に呼び出される関数
void AglTFRuntimeAssetActorAsync::ReceiveOnScenesLoaded_Implementation()
{

}
```

上記のように何も関数内で処理をしていません。

なのでAglTFRuntimeAssetActorAsyncを継承したクラスでReceiveOnScenesLoadedをオーバーライドして、処理としてイベントディスパッチャーを呼び出すようにします。

```C++:MyglTFRuntimeAssetActorAsync.h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "glTFRuntimeAssetActorAsync.h"
#include "MyglTFRuntimeAssetActorAsync.generated.h"

/**
 * 
 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FglTFRuntimeAssetActorDispatcher);

UCLASS()
class GLTF_API AMyglTFRuntimeAssetActorAsync : public AglTFRuntimeAssetActorAsync
{
	GENERATED_BODY()

public:
    // BP側でロード完了通知イベントバインドするためのイベントディスパッチャー
	UPROPERTY(BlueprintAssignable, Category = "glTFRuntime")
	FglTFRuntimeAssetActorDispatcher OnLoadCompleted;

    // ReceiveOnScenesLoaded関数のオーバーライド
	virtual void ReceiveOnScenesLoaded_Implementation() override;
};
```

```C++:MyglTFRuntimeAssetActorAsync.cpp
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyglTFRuntimeAssetActorAsync.h"

void AMyglTFRuntimeAssetActorAsync::ReceiveOnScenesLoaded_Implementation()
{
    Super::ReceiveOnScenesLoaded_Implementation(); 

    OnLoadCompleted.Broadcast();;
}
```

・BP側での実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498810/a5880e29-1058-fb16-2a48-b59969269c90.png)

これでBP側でロード完了時の通知を受け取ることができるようになりました。
ロードの進捗もBP側で受け取ることはデフォルトではできません。プラグインの改造を行えば可能ですが、保守性が悪いため現在開発元にプルリクをしています（部分的にでもマージされると嬉しい）。