ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Unreal Engine] USaveGame templatize
    Unreal Engine 5._ 2023. 10. 1. 19:26

    지난 글(Save&Load)에서 USaveGame객체를 이용해 언리얼 엔진에서 제공하는 Save, Load기능을 사용하는 방법을 알아보았습니다.

    이번 글은 지난 글에 이어, 해당 기능을 조금 간편하게 활용할 수 있는 방법을 고찰해보도록 하겠습니다.

     


     

    지난 글에서 살펴 본 Save & Load의 특징 중 일부는 다음과 같습니다.

    1. USaveGame을 상속받은 객체의 값을 Save, Load합니다.
    2. 데이터에 대한 Mapping 수단으로 (해당 데이터를 찾는 방법으로) 문자열을 사용합니다.
    3. 문자열은 Save, Load함수에서 각각 독립적으로 입력됩니다.

    위와 같은 특징을 생각해보았을 때, Save와 Load시 입력되는 문자열이 달라지거나, 다른 USaveGame객체를 사용하게 되는 등의 경우에 대하여 확장성이 부족하다고 판단했습니다.

     

    다음 내용은 위 이슈를 해결하기 위해 사용 된 방법입니다.

     

    1. enum class SaveType

     

    더보기

    다음과 같이 enum class를 정의했습니다.

    enum class SaveType {
        ActorA = 0,
        ActorB = 1,
        ActorC = 2,
        ...
    }

    위와 같이, 저장이 필요한 액터들의 열거형을 정의해줍니다.

    해당 열거형은 다음 문단의 Save, Load를 Wrapping한 객체에서 사용됩니다.

     

    2. MySaveSystem

     

    더보기

    Save, Load기능을 Wrapping한 객체를 추가했습니다.

    해당 객체는 기존의 Save, Load에 일부 기능을 추가 한 객체입니다.

     

    다음 함수는 SaveType열거형을 문자열로 변환하는 함수입니다.

    FString MySaveSystem::SaveFileName(SaveType saveType, int32 id) {
        const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("SaveType"), true);
        if (!EnumPtr) return FString("Invalid");
    
        FString fileName = EnumPtr->GetNameStringByIndex((int32)saveType);
    
        if (id == -1) return fileName;
        else return fileName + TEXT("_") + FString::FromInt(id);
    }

    위 함수는 SaveType열거형을 문자열로 변환합니다.

    이 때, id라는 값을 추가로 받아 해당 값이 -1이 아닐 때, SaveType_ID와 같은 문자열을 생성합니다.

    Id를 추가하는 해당 기능은 동일한 객체를 다수 저장할 때 사용하기 위해 추가했습니다.

     

    다음 함수는 Save, Load기능을 Wrapping한 함수입니다.

    // Save
    bool MySaveSystem::Save(USaveGame* saveGame, SaveType saveType, int32 id) {
        if (UGameplayStatics::SaveGameToSlot(saveGame, SaveFileName(saveType, id), 0)) {
            return true;
        }
        else {
            return false;
        }
    }
    
    // Load
    USaveGame* MySaveSystem::Load(SaveType saveType, int32 id) {
        return UGameplayStatics::LoadGameFromSlot(SaveFileName(SaveActor, id), 0);;
    }

    두 함수 모두 기존의 Save, Load함수를 호출하지만, 저장 될 파일 이름에 SaveFileName함수를 사용합니다.

     

    위 함수를 호출하는 예제 코드는 다음과 같이 될 수 있습니다.

    // Save
    void AMyActor::Save() {
        UMySaveGame* tmp = Cast<UMySaveGame>(
            UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
        tmp->data = this->data;
        
        mySaveSystem->Save(tmp, SaveType::MyActor);
    }
    
    // Load
    bool AMyActor::Load() {
        UMySaveGame* tmp = Cast<UMySaveGame>(
            mySaveSystem->Load(SaveType::MyActor));
        
        if(!tmp) return false;
        
        this->data = tmp->data;
        return true;
    }

     


     

    위와 같이 Warpping할 경우 저장되는 파일 이름을 신경쓰지 않아도 된다는 이점이 생깁니다.

    이는 이후 프로그램의 기능이 변경되거나 하는 이유로, 파일 이름이 바뀌어야 되는 상황에 쉽게 대응할 수 있습니다.

     

    이 글이 도움이 되셨기를 바랍니다.

    감사합니다.

    댓글

Designed by Tistory.