3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-03-04

初めに

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

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

そこで他に何か使えそうなプラグインはないか探してみたところ、マーケットプレイス内でglTFRuntimeプラグイン(投稿時有料)を見つけました。
非同期でロードしたり、アニメーションの有無や、コリジョンの設定など様々な設定ができます。
基本的な使用方法は公式ドキュメントでまとまっています。
使い方が分からない部分に関してはDiscordで聞くと早く回答してもらえます。

環境情報

Windows 11
UE 5.3.2
glTFRuntimeバージョン:20231127

ロード完了通知の設定方法

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

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

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をオーバーライドして、処理としてイベントディスパッチャーを呼び出すようにします。

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;
};
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

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

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?