서비스
교육 철학

Configuration (설정) 시스템

Abstract

📌
Config 는 코드에 박아 넣던 상수를 텍스트 파일로 꺼내 놓는 곳입니다. const int MaxEnemies = 13; 을 config.GetInt("Spawn.MaxEnemies", 13) 으로 바꾸면, 그 숫자를 고치기 위해 프로그래머가 재컴파일할 필요가 없어집니다. 구조는 이름 하나에 값 하나 — 가장 단순한 데이터 모듈입니다.
실무에서 필요한 순간
•
밸런스 손잡이. 스폰 상한, 무적 시간, 드랍 확률처럼 플레이 테스트하며 계속 만지는 숫자
•
기능 스위치. Feature.Ads = false 로 광고를 끄고 내보낸 뒤, 준비되면 값만 바꾼다
•
환경별 값. 개발 서버 주소 / 운영 서버 주소
•
빌드 없이 바꾸기. 설정 파일을 Addressables 원격 그룹에 두거나 서버에서 받아 ParseData 로 덮어쓴다
행이 여러 개인 표(적 5종의 스탯)는 DataTable 의 몫이고, Config 는 낱개 값에 씁니다.
값은 네 가지 모양으로 한꺼번에 저장된다
파일에서 "13" 이라는 문자열을 읽으면 코어는 그 자리에서 bool / int / float / string 네 가지로 모두 변환해 저장합니다. 그래서 꺼낼 때는 변환 비용이 없고, 같은 값을 GetInt 로도 GetString 으로도 꺼낼 수 있습니다. 대신 파일에는 타입 정보가 없습니다 — "abc" 를 GetInt 로 꺼내면 예외가 아니라 조용히 0 이 나옵니다.
ConfigComponent config = GameEntry.GetComponent<ConfigComponent>(); // 기본값을 주는 쪽을 쓴다. 키가 없어도 예외가 나지 않는다 int maxEnemies = config.GetInt("Spawn.MaxEnemies", 13); float invincible = config.GetFloat("Player.InvincibleSeconds", 1.5f); bool showFps = config.GetBool("Debug.ShowFps", false);
C#
복사
ToyboxNightmare 에 적용한다면
지금 EnemyTable 에 const 로 박힌 값들이 후보입니다.
지금 (C# 상수)
Config 로 옮기면
EnemyTable.RetargetInterval = 0.5f
Enemy.RetargetInterval 0.5
EnemyTable.DeathEffectTime = 2f
Enemy.DeathEffectTime 2
EnemyTable.SinkSpeed = 2.5f
Enemy.SinkSpeed 2.5
옮길 때는 매 프레임 GetFloat 를 부르지 말고, 로드 완료 시점에 한 번 읽어 필드에 넣어 둡니다. 딕셔너리 조회라 빠르긴 하지만 문자열 해시 계산이 매번 듭니다.
⚠️
자주 걸리는 곳
•
소수는 항상 점(.)으로 적습니다. 값은 기기 언어와 무관하게(InvariantCulture) 해석되므로 0.5 는 어느 나라 기기에서든 0.5 입니다. 원작은 기기 언어를 따라 해석해서 소수점이 쉼표인 지역(독일어·프랑스어 등)의 기기에서 0.5 를 잘못 읽었고, 이 에디션에서 고쳤습니다.
•
기본값 없는 GetInt(name) 은 키가 없으면 예외입니다(Config name '…' is not exist.). 기본값을 받는 오버로드를 쓰는 편이 안전합니다.
•
같은 키는 덮어써지지 않습니다. 파일을 읽다가 이미 있는 키를 만나면 경고 로그를 남기고 그 줄에서 파싱을 중단합니다(뒤의 줄은 읽히지 않음). 파일을 여러 개 읽어 덮어쓰려면 먼저 RemoveConfig 하거나 RemoveAllConfigs 후 다시 읽습니다.
•
기본 헬퍼의 파일 형식은 탭으로 구분된 4열(2열 = 이름, 4열 = 값)입니다. 위 표의 "이름 탭 값"은 설명을 위해 줄인 것이고 실제 줄은 Enemy.SinkSpeed (메모) 2.5 모양입니다.
•
본문 "시스템 초기화"의 SetResourceManager 등은 ConfigComponent 가 대신 하고, ReadData("GameConfig.txt") 의 인자는 이 에디션에서 파일명이 아니라 Addressables 주소입니다. 결과는 LoadConfigSuccessEventArgs 이벤트로 받습니다.

Configuration (설정) 시스템

관련 소스 파일

•
GameFramework/Config/ConfigManager.cs
•
GameFramework/Config/IConfigHelper.cs
•
GameFramework/Config/IConfigManager.cs
•
GameFramework/DataTable/DataTableManager.cs
•
GameFramework/DataTable/IDataTableHelper.cs
•
GameFramework/DataTable/IDataTableManager.cs
•
GameFramework/Localization/ILocalizationHelper.cs
•
GameFramework/Localization/ILocalizationManager.cs
•
GameFramework/Localization/LocalizationManager.cs

소개

Game Framework의 Configuration(설정) 시스템은 전역 게임 설정을 관리하는 중앙화된 메커니즘을 제공합니다.
이 시스템은 게임 동작의 다양한 측면을 제어하는 키-값(key-value) 쌍의 설정 데이터를 저장, 조회, 수정할 수 있도록 해줍니다.
•
Data Table 시스템이 구조화된 게임 데이터를 처리하는 것과 달리,
•
Localization 시스템이 언어별 텍스트를 처리하는 것과 달리,
•
Configuration 시스템은 단순하고 전역에서 접근 가능한 게임 설정에 초점을 맞춥니다.

시스템 아키텍처

Configuration 시스템은 ConfigManager 클래스와 그 지원 컴포넌트를 중심으로 구성됩니다.
이 시스템은 boolean, integer, float, string의 다양한 형식으로 값을 저장하고 조회할 수 있는 유연한 메커니즘을 제공합니다.

주요 구성 요소

•
IConfigManager : 설정 관리 API를 정의하는 인터페이스
•
ConfigManager : 설정 관리자 구현체
•
ConfigData : 설정 값을 여러 형식으로 저장하는 내부 구조체
•
IConfigHelper : 플랫폼별 설정 유틸리티를 위한 인터페이스

설정 데이터 구조

각 설정 항목은 ConfigData 구조체에 저장되며, 다음 네 가지 형식의 값이 동시에 유지됩니다.
1.
Boolean 값
2.
Integer 값
3.
Float 값
4.
String 값
값이 추가될 때 네 가지 형식으로 모두 파싱되어 저장되므로, 나중에 조회 시 변환 과정 없이 효율적으로 접근할 수 있습니다.

설정 로딩 파이프라인

Configuration 시스템은 리소스 매니저, 데이터 프로바이더, 설정 헬퍼를 사용하여 설정 데이터를 읽어들입니다.

Configuration 시스템 사용법

1. 시스템 초기화

// ConfigManager 인스턴스 얻기 IConfigManager configManager = GameFrameworkEntry.GetModule<IConfigManager>(); // 의존성 주입 configManager.SetResourceManager(resourceManager); configManager.SetDataProviderHelper(dataProviderHelper); configManager.SetConfigHelper(configHelper);
C#
복사

2. 설정 값 읽기

존재 여부 확인
bool exists = configManager.HasConfig("MusicVolume");
C#
복사
값 가져오기 (없으면 예외 발생)
bool enableMusic = configManager.GetBool("EnableMusic"); int enemyCount = configManager.GetInt("EnemyCount"); float movementSpeed = configManager.GetFloat("MovementSpeed"); string serverAddress = configManager.GetString("ServerAddress");
C#
복사
기본값을 설정하여 가져오기 (없어도 안전)
bool enableVibration = configManager.GetBool("EnableVibration", false); int maxPlayers = configManager.GetInt("MaxPlayers", 4); float timescale = configManager.GetFloat("Timescale", 1.0f); string defaultName = configManager.GetString("DefaultName", "Player");
C#
복사

3. 설정 추가/삭제

// 새로운 설정 추가 configManager.AddConfig("NewSetting", "true"); // 형식별 값 지정하여 추가 configManager.AddConfig("ComplexSetting", true, 42, 3.14f, "Hello"); // 설정 삭제 configManager.RemoveConfig("ObsoleteSetting"); // 모든 설정 제거 configManager.RemoveAllConfigs();
C#
복사

4. 외부 리소스에서 설정 로드

// 설정 파일 로드 configManager.ReadData("GameConfig.txt"); // 우선순위 지정하여 로드 configManager.ReadData("GameConfig.txt", 100); // 사용자 데이터와 함께 로드 configManager.ReadData("GameConfig.txt", userData); // 로딩 이벤트 핸들링 configManager.ReadDataSuccess += OnConfigLoadSuccess; configManager.ReadDataFailure += OnConfigLoadFailure;
C#
복사

다른 프레임워크 시스템과의 관계

시스템
목적
구조
지속성
사용 예시
Configuration
전역 게임 설정
단순 key-value
런타임 전용
게임 파라미터, 플래그, 설정
Data Table
구조화된 게임 데이터
ID 기반 행(Row)
런타임 전용
캐릭터 스탯, 아이템
Localization
언어별 텍스트
언어 키 딕셔너리
런타임 전용
UI 텍스트, 대사
Setting
사용자 설정
직렬화 가능 값
세션 간 지속
세이브 데이터
Data Node
계층적 데이터
트리 구조
런타임 전용
복잡한 게임 상태

ConfigData 구조 예시

public bool AddConfig(string configName, string configValue) { bool boolValue = false; bool.TryParse(configValue, out boolValue); int intValue = 0; int.TryParse(configValue, out intValue); float floatValue = 0f; float.TryParse(configValue, out floatValue); return AddConfig(configName, boolValue, intValue, floatValue, configValue); }
C#
복사
→ 문자열 값이 입력되면, Boolean / Int / Float / String 네 가지 형태로 모두 변환하여 저장합니다.

베스트 프랙티스

1.
초기화 순서
•
다른 시스템이 의존하기 전에 게임 시작 시 가장 먼저 초기화
2.
기본값 활용
•
설정이 없을 경우 안전하게 기본값을 반환하는 오버로드 사용
3.
설정 네이밍 규칙
•
"Graphics.Quality", "Audio.Volume"처럼 그룹화
4.
에러 처리
•
파일 로드 실패, 필수 설정 누락 시 처리 로직 추가
5.
값 검증
•
범위와 형식을 체크 후 저장
6.
캐싱
•
자주 쓰는 설정 값은 별도 변수에 저장하여 반복 조회 최소화