0. 설명
참고 : 비동기 애셋 로딩
FStreamableManager::RequestAsyncLoad 함수를 이용한 Asset async load 코드 예제.
BeginPlay시 임의의 SkeletalMesh를 비동기 로드하고, 이를 SkeletalMeshComponent에 SetSkeletal 하는 코드.
1) GEngine / UAssetManager
UAssetManager는 UEngine 클래스의 멤버 변수이며, UEngine 클래스는 다음과 같이 전역 변수로 존재한다.
// Runtime/Engine/Classes/Engine/Engine.h
/**
* Abstract base class of all Engine classes, responsible for management of systems critical to editor or game systems.
* Also defines default classes for certain engine systems.
*/
UCLASS(abstract, config=Engine, defaultconfig, transient)
class ENGINE_API UEngine
: public UObject, public FExec
{
// ...
UPROPERTY()
class UAssetManager *AssetManager;
// ...
};
/** Global engine pointer. Can be 0 so don't use without checking. */
extern ENGINE_API class UEngine* GEngine;
UAssetManager 역시 Singleton 개념을 가지고 있다.
2) UAssetManager::RequestAsyncLoad
RequestAsyncLoad 함수의 시그너쳐는 다음과 같다.
// Runtime/Engine/Classes/Engine/StreamableManager.h
TSharedPtr<FStreamableHandle> UAssetManager::RequestAsyncLoad
(
// 디스크로부터 로드할 애셋 스트림
const FStringAssetReference& TargetToStream,
// 비동기 수행 완료시 호출할 델리게이트
FStreamableDelegate DelegateToCall = FStreamDelegate(),
// 우선순위, 높을수록 빨리 완료
TAsyncLoadPriority Priority = 0,
// true : AssetManager는 FStreamableHandle을 명시적으로 release하기 전까지 active 상태로 보관
bool bManageActiveHandle = false,
// 반환 핸들의 이름이자 디버깅 도구에서 드러날 이름
const FString& DebugName = L"RequestAsyncLoad SingleDelegate"
)
첫번째 인자인 TargetToStream을 제외하고는 모두 default paremeter임을 확인할 수 있다.
1. Code
///////////////////////////////////////////////////////////////////////////////////////////////
// Header
///////////////////////////////////////////////////////////////////////////////////////////////
// Load from DefaultGame.ini
UPROPERTY(Config)
TArray<FStringAssetReference> CharacterAssets;
///////////////////////////////////////////////////////////////////////////////////////////////
// CPP
///////////////////////////////////////////////////////////////////////////////////////////////
// Called when the game starts or when spawned
void AABPawn::BeginPlay()
{
Super::BeginPlay();
// pick character SkeletalMesh index
CharacterSKIndex = FMath::RandRange(0, CharacterAssets.Num() - 1);
// FStreamableManager
auto& assetLoader = UAssetManager::GetStreamableManager();
assetLoader.RequestAsyncLoad(
CharacterAssets[CharacterSKIndex],
FStreamableDelegate::CreateUObject(this, &AABPawn::CharacterMeshDeferred)
);
}
void AABPawn::CharacterMeshDeferred()
{
TAssetPtr<USkeletalMesh> NewCharacter(CharacterAssets[CharacterSKIndex]);
if (NewCharacter)
{
SkelMesh->SetSkeletalMesh(NewCharacter.Get());
}
}
언리얼 엔진에서 런타임에 애셋을 로딩하는 것은 UAssetManager::FStreamableManager 이다.
Line 23에서 UAssetManager::FStreamableManager를 GetStreamableManager 함수를 통해 얻어오는 것을 확인할 수 있다.
Line 26의 Delegate 및 바인딩에 대해서 사전 지식이 없다면 다음의 문서를 참고하기 바란다.
2. 참고
위 Code의 Line6에서 읽어들인 DefaultGame.ini는 다음과 같다.
[/Script/ArenaBattle.ABPawn]
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Barbarous.SK_CharM_Barbarous
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/sk_CharM_Base.sk_CharM_Base
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Bladed.SK_CharM_Bladed
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Cardboard.SK_CharM_Cardboard
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Forge.SK_CharM_Forge
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_FrostGiant.SK_CharM_FrostGiant
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Golden.SK_CharM_Golden
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Natural.SK_CharM_Natural
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Pit.SK_CharM_Pit
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Ragged0.SK_CharM_Ragged0
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_RaggedElite.SK_CharM_RaggedElite
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Ram.SK_CharM_Ram
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Robo.SK_CharM_Robo
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Shell.SK_CharM_Shell
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_solid.SK_CharM_solid
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Standard.SK_CharM_Standard
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Tusk.SK_CharM_Tusk
+CharacterAssets=/Game/InfinityBladeWarriors/Character/CompleteCharacters/SK_CharM_Warrior.SK_CharM_Warrior
위 ini에서 보여지듯, 앞에 + 기호가 붙으면 TArray 형식으로 ini로부터 값을 읽어들일 수 있다.
'UE4' 카테고리의 다른 글
[UE4] Actor::RootComponent (0) | 2023.04.24 |
---|---|
[UE4] ConstructorHelper::FObjectFinder/FClassFinder (0) | 2023.04.24 |
[UE4] FTimerManager::SetTimer/ClearTimer/GetTimerElapsed (0) | 2023.04.24 |
[UE4] World 내 Object/Actor 순회 (0) | 2023.04.24 |
[UE4] MyLogMacro.h (0) | 2023.04.24 |