[Unreal] 이득우 Part 1. 3강 언리얼C++ 기본타입과 문자열

Kim Dongil·2024년 3월 16일
0

언리얼엔진

목록 보기
7/18

시작

  • 언리얼 환경에서 알아두어야 할 기본 타입과 고려할 점
  • 캐릭터 인코딩 시스템에 대한 이해
  • 언리얼 C++이 제공하는 다양한 문자열 처리 방법과 내부 구성의 이해
  • FString의 구조와 사용 방법
  • FName의 구조와 사용 방법

왜 언리얼은 기본 타입을 따로 지정하는가?

  • int는 32비트 또는 64비트로 해석될 수 있다.
    따라서 데이터를 저장할 때 int 타입의 크기를 확신 할 수 없다.
  • 네트웍 상에서 데이터 통신이 효율적이고 안정적이어야 한다.
  • 데이터 정보가 명확해야 한다.

-> 때문에 후발 언어인 C#의 경우 4바이트인 int32로 명확히 정의되어있다.
-> 언리얼은 int를 사용하지 않고 int32를 사용한다.

언리얼 C++ 기본 타입

bool 타입

  • 크기가 명확하지 않음
  • 헤더에는 가급적 bool 대신 uint8 타입을 사용하되 Bit Field 오퍼레이터 사용
  • 일반 uint8과의 구분을 위해 b접두사 사용
  • Cpp 로직에서는 자유롭게 bool 사용

캐릭터 인코딩

언리얼엔진 캐릭터 인코딩

  • 언리얼은 내부적으로 모두 UTF-16을 사용
  • 텍스트 파일 로드도 UTF-16으로 로드
  • 소스 코드 같은 경우에는 많이 사용되는 UTF-8을 사용해서 저장

언리얼 문자열 처리

  • 2바이트로 사이즈가 균일한 UTF-16 사용
  • 언리얼 표준 캐릭터 타입: TCHAR
  • TEXT 매크로를 사용해서 TCHAR을 사용
  • 문자열 클래스 FString 제공

FString

언리얼엔진 FString

  • TCHAR의 동적배열을 소유하고 있는 클래스
  • 다양한 구조체들이 ToString()을 통해 FString으로 변환해서 디버깅을 할 수 있도록 해줌
  • 비교, 검색, 조립
  • 복잡한 문자를 생성하고 싶으면 Printf()를 사용
  • 인코딩 매크로 제공

*연산자를 사용한다면 FString에 포함하고 있는 동적 배열 TArray가 포함하고 있는 첫 번째 인자의 포인터를 반환한다.

FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString);

또 FString 내부적으로는 FCString 클래스가 있다.
이 클래스는 일종의 C라이브러리에서 제공하는 기본적인 스트링 관련 함수들을 포함하고 있는 래퍼 클래스로 생각하면 된다.
그래서 FString은 데이터를 보관하지만 실제로 사용하는 유틸 함수들은 FCString을 통해가지고 진행한다.

const TCHAR* lOGcHARpTR = *LogCharString;
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData();

*연산자를 사용하면 const TCHAR* 타입으로 첫 번째 인자 포인터를 받고, GetCharArray().GetData() 를 사용하여 const가 안붙은 TCHAR 포인터를 가져오므로 메모리에 직접 접근해서 사용 가능하다.

TCHAR LogCharArrayWithSize[100];
FCString::Strcpy(LogCharArrayWithSize, LogCharString.Len(), *LogCharString);

다시 배열로 가져오고 싶다면 배열 크기를 선언하고, 저수준 스트링 복사를 해준다.

FString 함수

if (LogCharString.Contains(TEXT("unreal"), ESearchCase::IgnoreCase))
{
	int32 Index = LogCharString.Find(TEXT("unreal"), ESearchCase::IgnoreCase);
	FString EndString = LogCharString.Mid(Index);
	UE_LOG(LogTemp, Log, TEXT("Find Test: %s"), *EndString);
}

FString Left, Right;
if (LogCharString.Split(TEXT(" "), &Left, &Right))
{
	UE_LOG(LogTemp, Log, TEXT("Split Test : %s 와 %s"), *Left, *Right);
}
  • Contains: 특정 문자열을 포함하고 있는지
    Find: 인덱스 찾기
  • ESearchCase::CaseSensitive -> 대소문자 구분
  • ESearchCase::IgnoreCase -> 대소문자 구분 x
  • Mid: 해당 인덱스부터 뒤로 자르기
  • Split: 해당 FString 앞 뒤 자르기

이 때 실행해보면

이렇게 '와' 를 제대로 출력하지 못하고 있다.


파일 -> 다른 이름으로 저장 -> 인코딩 저장 -> UTF-8 로 설정해주면 해결된다.

int32 IntValue = 32;
float FloatValue = 3.141592;

FString FloatIntString = FString::Printf(TEXT("int:%d Float:%f"), IntValue, FloatValue);
FString FloatString = FString::SanitizeFloat(FloatValue);
FString IntString = FString::FromInt(IntValue);

UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString);
UE_LOG(LogTemp, Log, TEXT("int:%s float:%f"), *IntString, *FloatString);

  • FString::Printf: 복잡한 문자열 합성
  • FString::SanitizeFloat: Float -> String
  • FString::FromInt: Int -> String

FString으로 변환

언리얼이 제공하는 다양한 문자열 처리

FName

언리얼엔진 FName

  • FName : 에셋 관리를 위해 사용되는 문자열 체계

    • 대소문자 구분 없음
    • 한번 선언되면 바꿀 수 없음
    • 가볍고 빠름
    • 문자를 표현하는 용도가 아닌 에셋 키를 지정하는 용도로 사용. (빌드시 해시값으로 변환됨)
    • 언리얼은 FName과 관련된 글로벌 Pool 자료구조를 가지고 있음
    • FName과 글로벌 POOL
      • 문자열이 들어오면 해시 값을 추출해 키를 생성해 FName에서 보관
      • FName 값에 저장된 값을 사용해 전역 Pool에서 원하는 자료를 검색해 반환
      • 문자 정보는 대소문자를 구분하지 않고 저장 (IgnoreCase)
    • FName의 형성
      • 생성자에 문자열 정보를 넣으면 풀을 조사해 적당한 키로 변환하는 작업이 수반됨
      • Find or Add

즉 문자열 정보는 어딘가 따로 저장이 되고, 문자열을 변환해서 해시 값과 키값이 저장이 된다. 그래서 키 값을 사용해서 Pool에 있는지 없는지를 빠르게 검출을 하고 있다면 그 값을 사용해가지고 원하는 데이터를 가져오는 형태로 구성되어 있다.

-> 실제적인 자료는 키 값만 갖고있기에 용량은 굉장히 작고 데이터가 있는지 찾거나 없으면 추가하거나 하는 행동밖에 할 수가 없다.

FName Key1(TEXT("PELVIS"));
FName Key2(TEXT("pelvis"));
UE_LOG(LogTemp, Log, TEXT("FName 비교 결과 : %s "), Key1 == Key2 ? TEXT("같음") : TEXT("다름"));

주의 사항으로는 키가 전역 Pool에 있는지 조사하는 작업을 거치기에 오버헤드가 발생할 수 있으므로 반복문 사용시에 조심하자.

FText

  • FText: 다국어 지원을 위한 문자열 관리 체계
    • 일종의 키로 작용
    • 별도의 문자열 테이블 정보가 추가로 요구됨
    • 게임 빌드 시 자동으로 다양한 국가별 언어로 변환됨

0개의 댓글