icon
7장 : 저장 및 데이터 관리

사용자 설정과 환경 저장


이전 절들에서는 SaveGame 시스템과 일반 파일 입출력 및 JSON 처리를 통해 게임 데이터를 저장하고 관리하는 방법을 알아보았습니다. 이제 게임에서 매우 중요한 또 다른 종류의 데이터인 사용자 설정(User Settings)환경 설정(Environment Settings) 을 저장하고 관리하는 방법에 대해 살펴보겠습니다. 여기에는 그래픽 품질, 오디오 볼륨, 키 바인딩, 언어 설정 등 플레이어가 게임 경험을 개인화할 수 있는 모든 옵션이 포함됩니다.

언리얼 엔진은 이를 위해 특별히 고안된 UGameUserSettings 클래스를 제공합니다.


UGameUserSettings 시스템이란?

UGameUserSettings 는 플레이어별 게임 설정을 영구적으로 저장하고 로드하며 적용하는 데 사용되는 언리얼 엔진의 내장 시스템입니다. 이 시스템은 각 플레이어의 디바이스에 독립적인 .ini 파일 형태로 설정 데이터를 저장합니다.

UGameUserSettings의 주요 특징

  • 자동 저장/로드: 대부분의 기본 설정(해상도, 그래픽 품질 등)은 엔진에 의해 자동으로 처리됩니다.
  • 플랫폼 독립적: SaveGame 시스템과 마찬가지로, 다양한 플랫폼에서 일관된 방식으로 설정이 관리됩니다.
  • 쉬운 접근: UGameplayStatics::GetGameUserSettings() 함수를 통해 언제든지 현재 플레이어의 설정에 접근할 수 있습니다.
  • 확장성: 기본 설정을 넘어 게임 고유의 커스텀 설정을 추가하고 관리할 수 있습니다.
  • 설정 적용: 변경된 설정을 게임에 즉시 적용하거나, 변경 사항을 임시로 저장했다가 나중에 일괄 적용할 수 있습니다.

커스텀 UGameUserSettings 클래스 생성

대부분의 프로젝트에서는 기본 UGameUserSettings 클래스를 직접 사용하는 대신, 이를 상속받아 게임 고유의 설정 변수를 추가합니다.

// MyGameUserSettings.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameUserSettings.h"
#include "MyGameUserSettings.generated.h"

UCLASS()
class MYPROJECT_API UMyGameUserSettings : public UGameUserSettings
{
    GENERATED_BODY()

public:
    UMyGameUserSettings();

    // 싱글톤 패턴처럼 어디서든 쉽게 접근할 수 있는 헬퍼 함수
    UFUNCTION(BlueprintCallable, Category = "Game Settings")
    static UMyGameUserSettings* GetMyGameUserSettings();

    //========================================
    // 커스텀 게임 설정 변수들
    // UPROPERTY로 선언해야 직렬화 대상이 됩니다.
    //========================================

    UPROPERTY(Config) // .ini 파일에 저장될 수 있도록 Config 지정
    float MasterVolume;

    UPROPERTY(Config)
    bool bShowPlayerHealthBar;

    UPROPERTY(Config)
    FString PlayerPreferredLanguage;

    UPROPERTY(Config)
    TArray<FKey> CustomAbilityKeyBinds; // 커스텀 능력 키 바인딩 (예시)

    //========================================
    // 커스텀 설정 제어 함수들
    //========================================

    UFUNCTION(BlueprintCallable, Category = "Game Settings")
    void SetMasterVolume(float NewVolume);

    UFUNCTION(BlueprintPure, Category = "Game Settings")
    float GetMasterVolume() const;

    UFUNCTION(BlueprintCallable, Category = "Game Settings")
    void SetShowPlayerHealthBar(bool bShow);

    UFUNCTION(BlueprintPure, Category = "Game Settings")
    bool GetShowPlayerHealthBar() const;

    UFUNCTION(BlueprintCallable, Category = "Game Settings")
    void SetPlayerPreferredLanguage(const FString& NewLanguage);

    UFUNCTION(BlueprintPure, Category = "Game Settings")
    FString GetPlayerPreferredLanguage() const;

    // 변경 사항을 .ini 파일에 저장 (부모 클래스 함수 오버라이드)
    virtual void SaveSettings() override;

    // 저장된 설정을 로드하거나 기본값을 적용 (부모 클래스 함수 오버라이드)
    virtual void LoadSettings(bool bForceReload = false) override;

    // 설정을 게임에 적용 (그래픽, 사운드 등)
    virtual void ApplySettings(bool bCheckFor===r= ===ssues) override;
};
// MyGameUserSettings.cpp
#include "MyGameUserSettings.h"
#include "Kismet/GameplayStatics.h"
#include "AudioDevice.h" // 오디오 볼륨 제어를 위해 포함 (선택 사항)
#include "GameFramework/PlayerController.h" // 플레이어 컨트롤러 접근을 위해 (선택 사항)
#include "Components/AudioComponent.h" // 사운드 컴포넌트 제어 (선택 사항)

UMyGameUserSettings::UMyGameUserSettings()
{
    // 기본값 설정
    MasterVolume = 0.75f;
    bShowPlayerHealthBar = true;
    PlayerPreferredLanguage = TEXT("en"); // 기본 언어 영어
    CustomAbilityKeyBinds.Add(EKeys::Q); // 기본 Q 키 바인딩
    CustomAbilityKeyBinds.Add(EKeys::E); // 기본 E 키 바인딩
}

UMyGameUserSettings* UMyGameUserSettings::GetMyGameUserSettings()
{
    // UGameplayStatics::GetGameUserSettings()는 항상 유효한 UGameUserSettings 인스턴스를 반환
    return Cast<UMyGameUserSettings>(UGameplayStatics::GetGameUserSettings());
}

void UMyGameUserSettings::SetMasterVolume(float NewVolume)
{
    MasterVolume = FMath::Clamp(NewVolume, 0.0f, 1.0f);
    // 변경 사항을 즉시 적용하고 싶다면 ApplySettings() 호출
    ApplySettings(false);
}

float UMyGameUserSettings::GetMasterVolume() const
{
    return MasterVolume;
}

void UMyGameUserSettings::SetShowPlayerHealthBar(bool bShow)
{
    bShowPlayerHealthBar = bShow;
    // UI 관련 설정은 주로 UI 위젯에서 직접 이 변수를 참조하여 처리합니다.
    // 즉시 UI 업데이트를 강제하려면 UI 관리자에게 알림을 보내야 합니다.
}

bool UMyGameUserSettings::GetShowPlayerHealthBar() const
{
    return bShowPlayerHealthBar;
}

void UMyGameUserSettings::SetPlayerPreferredLanguage(const FString& NewLanguage)
{
    PlayerPreferredLanguage = NewLanguage;
    // 언어 변경은 엔진의 로컬라이제이션 시스템을 통해 적용
    // FInternationalization::Get().SetCurrentCulture(NewLanguage); // 언어 변경
    // UGameplayStatics::SetCurrentCulture(NewLanguage); // Kismet 버전을 사용하면 더 편리
    ApplySettings(false); // 변경 사항 적용
}

FString UMyGameUserSettings::GetPlayerPreferredLanguage() const
{
    return PlayerPreferredLanguage;
}

void UMyGameUserSettings::SaveSettings()
{
    Super::SaveSettings(); // 부모 클래스의 SaveSettings 호출 (실제 파일 저장)
    UE_LOG(LogTemp, Warning, TEXT("MyGameUserSettings: Settings Saved!"));
}

void UMyGameUserSettings::LoadSettings(bool bForceReload)
{
    Super::LoadSettings(bForceReload); // 부모 클래스의 LoadSettings 호출
    UE_LOG(LogTemp, Warning, TEXT("MyGameUserSettings: Settings Loaded!"));

    // 로드된 후 필요에 따라 추가 초기화/유효성 검사 로직
    MasterVolume = FMath::Clamp(MasterVolume, 0.0f, 1.0f);
}

void UMyGameUserSettings::ApplySettings(bool bCheckFor=ssues)
{
    // 먼저 부모 클래스의 ApplySettings를 호출하여 기본 그래픽 설정 등을 적용
    Super::ApplySettings(bCheckFor===r= ===ssues); 
    UE_LOG(LogTemp, Warning, TEXT("MyGameUserSettings: Settings Applied!"));

    //========================================
    // 커스텀 설정 적용 로직
    //========================================

    // 마스터 볼륨 적용 (예시)
    // 모든 사운드 클래스에 대한 볼륨 설정은 Audio Mixer 또는 Sound Class Mixer를 통해 관리하는 것이 일반적입니다.
    // 여기서는 간단히 Audio Device를 통해 모든 사운드에 영향을 줄 수 있는 방법을 예시로 듭니다.
    FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();
    if (AudioDevice)
    {
        // Audio Device의 Listener Volume 또는 특정 Sound Class의 Volume을 조절
        // AudioDevice->SetMasterVolume(MasterVolume); // 이런 직접적인 함수는 일반적으로 사용되지 않음
        // 대신, Audio Mixer에 커스텀 마스터 볼륨 Sound Class를 만들고 그 볼륨을 제어하는 방식이 더 일반적
    }

    // 또는 특정 AudioComponent의 볼륨을 직접 제어
    // (이 방법은 모든 사운드에 적용되지 않으므로, 더 높은 수준의 오디오 시스템이 필요)
    // 예를 들어, 월드의 모든 Ambient Sound Actor의 볼륨을 조절해야 할 수도 있습니다.
    
    // 언어 설정 적용
    FInternationalization::Get().SetCurrentCulture(PlayerPreferredLanguage);

    // 키 바인딩 적용 (입력 시스템에 바인딩 로직 필요)
    // Project Settings -> Input -> Action Mappings 또는 Axis Mappings을 C++에서 동적으로 변경하는 것은 복잡합니다.
    // 보통은 FInputBindings와 같은 커스텀 시스템을 구축합니다.
    
    // 이외의 게임 관련 설정 (예: HUD 체력 바 표시 여부)
    // 이 설정은 주로 HUD 위젯에서 GetShowPlayerHealthBar()를 호출하여 조건부로 표시 여부를 결정합니다.
}

프로젝트 설정

프로젝트에서 UMyGameUserSettings를 사용하도록 엔진에 알려야 합니다. 이는 DefaultGameUserSettings.ini 파일에서 설정합니다.

  1. Config/DefaultGameUserSettings.ini 파일을 엽니다. (없다면 프로젝트 루트의 Config 폴더에 생성)

  2. 다음 내용을 추가하거나 수정합니다.

    [/Script/Engine.GameUserSettings]
    GameUserSettingsClassName=/Script/MYPROJECT.MyGameUserSettings
    • MYPROJECT는 여러분의 프로젝트 모듈 이름입니다.

이렇게 설정하면 엔진은 게임 시작 시 UMyGameUserSettings의 인스턴스를 자동으로 생성하고 로드/저장 로직을 관리합니다.


사용자 설정 활용 및 적용

C++에서 접근 및 변경

#include "MyGameUserSettings.h"

void AMyPlayerController::SetGameVolume(float NewVolume)
{
    UMyGameUserSettings* UserSettings = UMyGameUserSettings::GetMyGameUserSettings();
    if (UserSettings)
    {
        UserSettings->SetMasterVolume(NewVolume);
        // SaveSettings()는 SetMasterVolume 내부에서 호출될 수도 있고,
        // 옵션 메뉴에서 '적용' 버튼 클릭 시 일괄적으로 호출될 수도 있습니다.
        UserSettings->SaveSettings(); 
    }
}

블루프린트에서 접근 및 변경

Get My Game User Settings 노드를 사용하여 인스턴스를 얻은 후, 공개된 함수(BlueprintCallable, BlueprintPure)를 호출하여 설정을 읽거나 변경할 수 있습니다. Save SettingsApply Settings 노드를 사용하여 변경 사항을 저장하고 적용합니다.

이미지 출처: Unreal Engine Documentation (Save Game Settings with UMG)

설정 파일 위치

UGameUserSettings는 기본적으로 다음 위치에 설정을 저장합니다.

  • Windows: C:\Users\[사용자명]\AppData\Local\[프로젝트명]\Saved\Config\Windows\GameUserSettings.ini
  • Android/iOS: 각 플랫폼의 앱 데이터 디렉토리 내에 저장됩니다.

이 파일은 일반 텍스트 .ini 형식으로 되어 있어 직접 열어볼 수 있으며, Config 매크로를 사용한 변수들이 섹션 형태로 저장됩니다.

; GameUserSettings.ini 예시
[GameSettings]
MasterVolume=0.650000
bShowPlayerHealthBar=True
PlayerPreferredLanguage=ko
CustomAbilityKeyBinds=(Keys=((KeyName="Q",IsGamepadKey=False,IsMouseButton=False,IsAction=False,IsAxis=False,IsDeprecated=False,IsModifierKey=False,IsReadyForBind=False,IsBindableInSettings=False,IsCustomInput=False),(KeyName="E",IsGamepadKey=False,IsMouseButton=False,IsAction=False,IsAxis=False,IsDeprecated=False,IsModifierKey=False,IsReadyForBind=False,IsBindableInSettings=False,IsCustomInput=False)))

마치며

UGameUserSettings 시스템은 언리얼 엔진에서 사용자 설정과 환경을 효율적으로 관리하기 위한 표준적이고 강력한 방법입니다. 커스텀 클래스를 정의하고 Config 매크로를 사용하여 변수를 .ini 파일에 직렬화하며, SaveSettings()ApplySettings() 함수를 통해 설정을 저장하고 게임에 적용하는 방법을 익히면 플레이어에게 개인화된 게임 경험을 제공할 수 있습니다. 이는 게임의 접근성을 높이고 플레이어 만족도를 향상시키는 데 필수적인 요소입니다.

이것으로 7장 "저장 및 데이터 관리"를 마칩니다.