UDN
Search public documentation:

ConsoleManagerKR
English Translation
日本語訳
中国翻译

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > 엔진 프로그래밍 > 콘솔 매니저: C++ 의 콘솔 변수

콘솔 매니저: C++ 의 콘솔 변수


문서 변경내역: Martin Mittring 작성, 홍성진 번역.

개요


언리얼 엔진에 콘솔 명령이 생긴지는 오래 됐습니다. 명령이란 엔진에 전송되어 일정한 방식으로 (예를 들면 콘솔 텍스트로 응답한다든가, 내부 state를 변경한다든가 하는 식으로) 반응하는 사용자 입력 문자열을 말합니다.

새로운 콘솔 매니저로 흔히 쓰이는 패턴을 "콘솔 변수"로 통합하여 단순화시킬 수 있습니다.

콘솔 변수란 무엇인가?


콘솔 변수란 엔진 측면의 state를 저장하는 (float, int, string 등의) 단순 데이터형으로, 사용자가 그 state를 읽고 설정할 수도 있습니다. 콘솔 변수에는 이름이 있어 콘솔에 이름을 입력하기 시작하면 자동 완성 기능이 지원됩니다. 예를 들어

사용자 콘솔 입력 콘솔 출력 설명
MyConsoleVar MyConsoleVar = 0 변수의 현재 state가 콘솔에 출력됩니다.
MyConsoleVar 123 MyConsoleVar = 123 변수의 state가 바뀌고 새로운 state가 콘솔에 출력됩니다.
MyConsoleVar ? 아마도 도움말 여러 줄 콘솔 변수 도움말이 콘솔에 출력됩니다.

콘솔 변수 생성/등록하기


변수는 엔진이 생성되는 초기에 등록해 줘야 합니다. 예를 들어:

  GConsoleManager->RegisterConsoleVariable(TEXT("TonemapperType"),
     -1,
     TEXT("Allows to override which tonemapper function (during the post processing stage to transform HDR to LDR colors) is used:\n")
     TEXT("  -1 = use what is specified elsewhere\n")
     TEXT("   0 = off (no tonemapper)\n")
     TEXT("   1 = filmic approximation (s-curve, contrast enhances, changes saturation and hue)\n")
     TEXT("   2 = neutral soft white clamp (experimental)"),
     ECVF_Cheat);

GConsoleManager 가 글로벌 액세스 포인트이며, 여기서 콘솔 변수를 새로 등록하거나 이미 있던 것을 찾을 수 있습니다. 첫 파라미터는 콘솔 변수의 이름입니다 (유니코드). 둘째 파라미터는 디폴트 값이며, 이 상수의 타입에 따라 다양한 콘솔 변수 타입으로 만들 수 있습니다: int, float, string (FString).

RegisterConsoleVariableRef 에서도 기존 float 나 int 를 등록할 수도 있고, 간단히 콘솔 변수가 그 값을 사용하여 state 를 저장하게 할 수도 있습니다.

다음 파라미터는 사용자가 콘솔 변수 뒤에 "?" 를 붙이면 표시되는 도움말입니다.

다른 옵션 파라미터로 ECVF_Cheat 와 같은 옵션을 지정할 수 있습니다. 자세한 내용은 IConsoleManager.h 에 설명되어 있습니다.

콘솔 변수의 state 구하기


RegisterConsoleVariableRef 로 생성된 콘솔 변수의 state 는 등록할 때 사용한 변수로 쉽게 구할 수 있습니다.

(가상 함수 호출, 아마 캐시 실패 때문에) 약간 느리기만 할 뿐, GetInt(), GetFloat(), GetString() 등의 get 함수를 사용하여 state 를 구할 수 있다는 점 때문에 더 편합니다. 최적의 퍼포먼스를 위해서라면 등록된 변수와 같은 타입을 사용해 줘야 합니다. 변수로의 포인터를 구하려면 등록 함수의 반환 아규먼트를 저장하거나, 변수가 필요한 시점 직전에 FindConsoleVariable 를 호출하면 됩니다. 예를 들어:

   static IConsoleVariable* CVar = GConsoleManager->FindConsoleVariable(TEXT("TonemapperType"));

   INT Value = CVar->GetInt();

저기 static 을 통해 이 코드가 처음 호출됐을 때만 (맵으로 구현된) 이름 검색을 하도록 합니다. 변수가 절대 이동하지 않고 엔진 셧다운시에만 소멸되니 옳다 하겠습니다.

state 변경시 반응하기


ECVF_Changed 옵션을 사용하여 state 를 변경한 것이 Set() 메서드인지 사용자 입력인지를 알아볼 수 있습니다 (이 옵션을 트리거하지 않고도 변수로의 참조가 변경될 수 있음에 유의). 예를 들어:

   if(CVar->TestFlags(ECVF_Changed))
   {
      CVar->ClearFlags(ECVF_Changed);
      ...
   }

콘솔 변수 행위와 스타일에 의도된 사항


  • 콘솔 변수는 사용자 입력을 반영하나, (MotionBlur 0/1 같은 옵션은 지원하지 않는 플랫폼이 있을 수 있기에) 시스템의 state 까지 반영하지는 않습니다. 변수 state 는 코드로 변경하지 않는 것이 좋습니다. 왜냐하면 사용자가 지정한 state 가 변수에 반영되지 않으면 잘못 입력했나 혼란을 줄 수도 있고, 다른 변수의 state 때문에 콘솔 변수를 변경하지 못하게 될 수도 있기 때문입니다.
  • 항상 변수의 용도와 적정값을 설명해 주는 도움말을 작성해 주시기 바랍니다.
  • 대부분의 콘솔 변수는 개발 전용으로만 쓰이기에, 일찍 ECVF_Cheat 옵션을 붙여 주는 것도 좋은 생각입니다.
  • 변수 이름은 가급적 최소 길이로 하면서도 이름 자체로 설명이 되게끔 하는 것이 좋으며, 부정적인 의미는 피하는 것이 좋습니다 (나쁜 이름의 예: EnableMotionBlur, MotionBlurDisable, MBlur, HideMotionBlur). 대소문자를 적절히 사용하여 읽기 쉽고 일관되게 해 주시기 바랍니다 (예: MotionBlur).
  • 들여쓰기의 경우 (폭이 가변적이지 않은) 고정폭 폰트로 출력한다 가정하는 것이 좋습니다.

더 자세한 내용은 IConsoleManager.h 를 참고해 보시기 바랍니다.

콘솔 변수 로드하기

엔진 시동시 콘솔 변수의 스테이트는 "Engine/Config/ConsoleVariables.ini" 파일에서 로드할 수 있습니다. 더 자세한 내용은 파일 자체에서 찾아볼 수 있습니다:

; 이 파일로 엔진 시동시 (정의되지 않은 순서대로) 콘솔 변수를 설정할 수 있습니다.
; 현재 이 파일을 덮어쓰는 파일은 없습니다.
; 이 파일은 (코멘트에 대해, 그리고 코멘트를 찾을 위치를 알기 위해) 소스 콘트롤 데이터베이스에 있어야 하나,
; 변수로부터 공백 상태가 유지되었습니다.
; 반복되는 콘솔 변수 세팅을 타이핑할 시간을 절약하려면
; 개발자가 로컬에서 변경하면 됩니다. 변수는 [Startup] 부분에 있어야 합니다.
; 나중에
Later on we might have multiple named sections referenced by the section name.
; This would allow platform specific or level specific overrides.
; The name comparison is not case sensitive and if the variable doesn't exists it's silently ignored.
;
; Example file content:
;
; [Startup]
; FogDensity = 0.9
; ImageGrain = 0.5
; FreezeAtPosition = 2819.5520 416.2633 75.1500 65378 -25879 0

[Startup]

앞으로


  • 현재 시스템은 사용상의 편의를 위해 노골적으로 단순화된 상태입니다.
  • 콘솔 명령을 내리는 기능도 고려중입니다. (인터페이스 통일, callback 이나 deligate 사용, 자동 완성과 도움말 등)
  • 모든 해상도에서 도움말이 예쁘게 나오게 하려면 고정폭 폰트를 사용중인지, 최대 라인 폭 같은 것을 신경써야 합니다.
  • 현재 콘솔 변수는 C++ 로만 만들 수 있으나, 바뀔 수도 있습니다.
  • 변수 그룹도 생각해 볼 수 있습니다. 그런 용도로 쓸 앞글자나 문자열 시스템을 고려중입니다. (예: s_MusicBufferSize)
  • 모든 콘솔 변수와 도움말을 (소트, 그룹 적용하여) 출력하는 콘솔 명령을 추가할 계획입니다.
  • enum 과 bool 타입도 추가할 계획이었으나 문제가 많았습니다. 현재로서는 int 나 필요하면 string 을 사용하시기 바랍니다.
  • 도움말이 편하기는 합니다만 실행파일 크기 절약이나 치터 방지 목적으로, define 을 추가하여 도움말이 실행파일에 추가되지 않도록 하는 것을 고려중입니다.
  • 현재 자동 완성 기능에 일부 명령에 대한 한줄 도움말이 출력되기도 합니다. 이 기능은 콘솔 변수에 대해서는 꺼져 있습니다. 다른 한줄 도움말을 지정하거나 여러줄 도움말을 줄이지 않기 위함인데, 나중에 변경될 수 있습니다.

콘솔 변수 등록 해제하기

UnregisterConsoleVariable 메서드로 변수를 제거할 수 있습니다. 최소한 유저 관점에서는 그렇습니다. 포인터가 데이터에 접근할 때 크래시가 일어나지 않도록 변수를 (unregistered 플랙 설정 상태로) 유지는 시킵니다. 새 변수가 같은 이름으로 등록되면, 예전 변수가 복원되며, 새 변수에서 도움말과 옵션을 복사해 옵니다. 이런 식으로 변수 state 조차 그대로 유지하며 DLL 로딩과 언로딩이 가능한 것입니다. 참고로 콘솔 변수 참조에 대해서 작동하지 않기는 하지만, 하나만 포기하면 되기는 합니다: 포인터를 저장하지 말거나, 언레지스터 또는 참조를 사용하지 말거나요.

수동 콘솔 변수 구현과의 비교


예제:

몇몇 .cpp 파일, globals

   // 문서는 "MotionBlurSoftEdge" 콘솔 명령 참고
   FLOAT GMotionBlurSoftEdge = -1;

다른 몇몇 .cpp 파일, Exec() 메서드

   else if (ParseCommand(&Cmd, TEXT("MotionBlurSoftEdge")))
   {
      extern FLOAT GMotionBlurSoftEdge;
      FString Parameter(ParseToken(Cmd, 0));
      if(Parameter.Len())
      {
         GMotionBlurSoftEdge = appAtof(*Parameter);
      }
      else
      {
         Ar.Logf(TEXT("Allows to override the motion blur soft edge amount.\n"));
         Ar.Logf(TEXT("<0: use post process settings (default: -1)"));
         Ar.Logf(TEXT(" 0: override post process settings, feature is off"));
         Ar.Logf(TEXT(">0: override post process settings by the given value"));
      }
      Ar.Logf( TEXT("MotionBlurSoftEdge = %g"), GMotionBlurSoftEdge );
      return TRUE;
   }

BaseInput.ini 안

   ManualAutoCompleteList=(Command="MotionBlurSoftEdge",Desc="")

몇몇 함수 안에 사용:

   extern FLOAT GMotionBlurSoftEdge;
   ... use GMotionBlurSoftEdge ...

그 결과:

몇몇 .cpp 파일 안에, 엔진 스타트업시

   GConsoleManager->RegisterConsoleVariable(TEXT("MotionBlurSoftEdge"),
      -1.0f,
      TEXT("Allows to override the motion blur soft edge amount.\n")
      TEXT("<0: use post process settings (default: -1)\n")
      TEXT(" 0: override post process settings, feature is off\n")
      TEXT(">0: override post process settings by the given value"),
      ECVF_Cheat);

몇몇 함수 안에 사용:

   {
      static IConsoleVariable* CVar = GConsoleManager->FindConsoleVariable(TEXT("MotionBlurSoftEdge"));
      FLOAT Value = CVar->GetFloat();
      ... use Value ...
   }

콘솔 변수를 만들어 읽기 직전에는 더 작을 수도 있습니다. 아무튼 자동 완성 기능은 엔진 초기화 도중 변수를 등록해야 작동한다는 점이 중요합니다. 모든 콘솔 변수를 도움말 포함하여 출력하는 기능도 필요할 테니, 곧 구현하겠습니다.