INI 설정과 애셋의 지연로딩


  • ABCharacterSetting 은 앞으로 사용할 캐릭터 애셋의 목록을 보관한다.
  • INI 파일을 사용해 ABCharacterSetting의 기본값을 설정하는 방법을 진행
  • 애셋은 경로 정보만 알면 프로그램에서 참조해 로딩 할수 있다. 이 애셋 경로 정보를 보관하기 위해 언리얼 엔진은 FSoftObjectPath라는 클래스를 제공한다.
  • 언리얼 오브젝트가 기본값을 INI 파일에서 불러들이려면 UCLASS 매크로에 config 키워드를 추가해 여기에 불러들일 INIㅍ 알의 이름을 지정하고, 불러들일 PROPERTY 속성에는 config 키워드를 선언해야 한다.
  • 이렇게 서언하면 언리얼 엔진은 언리얼 오브젝트를 초기화할떄 해당 속성의 값을 INI 파일에서 읽어 설정한다.
//h
UCLASS(config=KGame)
class KGAMESETTING_API UABCharacterSetting : public UObject
{
    GENERATED_BODY()

public:
    UABCharacterSetting();
    UPROPERTY(config)
        TArray<FSoftObjectPath> CharacterAssets;
};

/cpp
#include "ABCharacterSetting.h"

UABCharacterSetting::UABCharacterSetting()
{

}

UCLASS 매크로 내 config 키워드네 있는 KGame이라는 설정으로 인해, 언리얼 엔진은 초기화 단계에서, Config 폴더에 위치한 DefaultKGame.ini 파일을 읽어 들여 , KGameSetting dnk CharacterAssets 값을 설정한다.
책에 리소스 DefaultKGame.ini 복사에서 Config 폴더로


 

  • 언리얼 엔진이 초기화 되면 엔진 구동에 필요한 모듈이 순차적으로 로딩된다. 모듈이 로딩되면서 모듈은 자신에게 속한 모든 언리얼 오브젝트의 기본값을 지정해 생성해낸다. 이를 클래스 기본 객체라고 한다.
  • 엔진이 초기화 되면 모든 언리얼 오브젝트 클래스 기본 객체가 메모리에 올라간 상태가 된다. 이렇게 올라간 클래스 기본 객체는 GetDefault 함수를 사용해 가져 올 수 있다. 엔진이 종료될떄까지 상주하기 떄문에 언제든지 사용해도 된다.
  • KGame 모듈에서 ABCharacter, KGameSettiing 모듈의 ABCharacterSetting에서 캐릭터 애셋 목록을 얻어오도록 코드를 생성한다. 그러러면 모듈의 빌드 규칙을 지정하는 KGame.Build.cs 파일에서 KGameSetting 모듈을 사용하도록 참조할 모듈 목록에 추가해야 한다.
  • 구현 부가 모여있는 Private 폴더 에서만 KGameSetting 모듈을 사용할 예정이므로 PricateDependencyModule 항목에 이를 추가한다.
public class KGame : ModuleRules
{
    public KGame(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG", "NavigationSystem", "AIModule", "GameplayTasks" });

        PrivateDependencyModuleNames.AddRange(new string[] { "KGameSetting" });

        // Uncomment if you are using Slate UI
        // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");

        // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
    }
}

성공 메시지 출력

  • 경로가 확인되고 생성자 로직에서 해당 코드는 제거하고, NPC가 생성될떄 랜덤하게 하나 캐릭터 애셋을 로딩하도록 기능을 변경한다.
  • 언리얼은 게임 진행 중 비동기 방식으로 애셋을 로딩하도록 FStreamableManager라는 클래스를 제공한다.
  • 이 매니저 클래스는 프로젝트에서 하나만 활성화 하는 것이 좋기에, 유일한 인스턴스로 동작하는 ABGameInstance 클래스에서 이를 멤버 변수로 선언한다.
class KGAME_API UABGameInstance : public UGameInstance
{
public:
    FStreamableManager StreamableManager;
};

//.h
class KGAME_API AABCharacter : public ACharacter
{
private:
    FSoftObjectPath CharacterAssetToLoad = FSoftObjectPath(nullptr);
    TSharedPtr<struct FStreamableHandle> AssetStreamingHandle;
}

//cpp
#include "ABGameInstance.h"

void AABCharacter::BeginPlay()
{

    if (!IsPlayerControlled())
    {
        auto DefaultSetting = GetDefault<UABCharacterSetting>();
        int32 RandIndex = FMath::RandRange(0,DefaultSetting->CharacterAssets.Num()-1 );
        CharacterAssetToLoad = DefaultSetting->CharacterAssets[RandIndex];

        auto ABGameInstance = Cast<UABGameInstance>(GetGameInstance());
        if (nullptr != ABGameInstance) {
            AssetStreamingHandle = ABGameInstance->StreamableManager.RequestAsyncLoad( 
                CharacterAssetToLoad, FStreamableDelegate::CreateUObject(this, &AABCharacter::OnAssetLoadCompleted));     //완료가 되면 등록한 함수가 호출 된다.
        }
    }
}

void AABCharacter::OnAssetLoadCompleted()
{
    AssetStreamingHandle->ReleaseHandle();
    TSoftObjectPtr<USkeletalMesh> LoadedAssetPath(CharacterAssetToLoad);
    if (LoadedAssetPath.IsValid())
    {
        GetMesh()->SetSkeletalMesh(LoadedAssetPath.Get());
    }
}

FStreamableDelegate::CreateUObject () : 즉석 델리게이트 생성 
FStreamableHandle : A handle to a synchronous or async load. As long as the handle is Active, loaded assets will stay in memory
TSoftObjectPtr : TSoftObjectPtr is templatized wrapper of the generic FSoftObjectPtr , it can be used in UProperties

+ Recent posts