강의 목표 :
- 언리얼 환경에서 알아두어야 할 기본 타입과 고려할 점
- 캐릭터 인코딩 시스템에 대한 이해
- 언리얼 C++이 제공하는 다양한 문자열 처리 방법과 내부 구성의 이해
강의 내용 :
- 언리얼이 C++ 타입 int 를 사용하지 않는 이유
- 다양한 캐릭터 인코딩 시스템
- 언리얼의 문자열 이해
- FString의 구조와 사용 방법
- FName의 구조와 사용 방법
[ ✔️기본 타입 ]
📍따로 지정하는 이유 :
- C++ 언어는 1970년대에 개발되었다. ( 엄청 오래됨)
- 플랫폼마다 C언어를 구현하는 방법이 달랐다. (플랫폼 파편화, Platform Fragmentation)
- 최신 규약에서 int는 최소 32비트를 보장하도록 규정되어 있지만 어떤 플랫폼에선 64비트로 해석될 수 있다. (int 타입의 크기 모호)
📍게임 제작의 특징 :
게임 제작의 경우 단일 컴퓨터에서 최대의 포퍼먼스를 끌어 올리는 것을 목표로 둬야한다.
이를 위해선 캐시 히트율을 신경써서 자료구조를 만들어야한다.
캐시 히트율 :
캐시된 데이터를 요청할 때 해당 키 값이 메모리에 존재하여 얼마만큼의 비율로 잘 찾았는지에 대한 여부.
즉, 캐시에 있는지 확인했을 때, 존재한 횟수가 얼마나 많은가? 를 의미함
- 데이터 정보가 명확해야한다.
- 단일 컴퓨터에서 최대 퍼포먼스를 뽑아야 한다.
- 네트웍 상에서 데이터 통신이 효율적이고 안정적이어야 한다.
📍언리얼 엔진에서 주로 사용하는 기본 타입 :
- int32 : int 처럼 사용
- uint8 : 바이트 정보를 사용할 때 일반적으로 사용
- TCHAR : character 를 의미함
- float, double : 실수 자료형
📍bool 타입 :
- 크기가 명확히 명시되어 있지 않다.
- 헤더에서는 가급적 bool 대신에 uint8 타입을 사용한다.
- 참과 거짓을 나타내는데 바이트 단위의 메모리를 사용하는건 메모리적으로 손해다.
- BitField 오퍼레이터를 활용하여 데이터의 크기를 제한시켜준다.
- 일반 uint8 와의 구분을 위해 "b접두사" 를 사용
- 구현부(cpp 파일)에서는 자유롭게 bool 타입 사용 가능
UPROPERTY()
uint8 bNetTemporary:1;
// 위와 같은 방식으로 Bit Field Operator 사용 가능
[ ✔️문자열 ]
📍따로 지정하는 이유 :
- 1990년대 후반에 표준화된 아시안 문자열 표준 (한국, 중국, 일본)
- 모든 문자열이 아직 사용되고 있다. 때문에 문자열 종류가 다양해져버렸다.
📍문자열 처리의 종류 :
- Single byte(ANSI, ASCII) : 초창기
- Multibyte(EUC-KR, CP949) : 보급기 (1990년대 초중반)
- Unicode(UTF-8, UTF-16) : 국제 표준 정착기 (1990년대 후반)
📍텍스트 포멧의 표준 :
동아시아를 배려하지 않은 ASCII, ANSI
동아시아(대한민국, 일본, etc ...)를 고려해준 UTF-8, UTF-16
UTF-8 | UTF-16 | |
장점 | 1. 메모리를 적게 사용 2. 아스키의 상위 개념으로 영어만 사용한다면 아스키와 완전히 호환된다. |
1. 필요한 모든 글자에 간단하게 접근할 수 있다. 2. 2바이트 고정이라, 메모리 연산이 필요없다. → 메모리 사용량은 글자수의 2배 3. 균일한 구성과 깔끔한 데이터를 받을 수 있다. |
단점 | 필요한 모든 글자에 대해 접근하기가 다소 불편하다. | UTF-8 보다는 메모리를 많이 사용한다. |
📍언리얼의 방식 :
문자열 종류 3개를 고려하는 대신 하나만 고려하는 차원에서 TCHAR 문자열 처리 방식을 지원함
내부적으로 모두 UTF-16 방식으로 끌어온다.
- 가능하면 소스코드에는 영문을 사용해라.
- 만약 한글을 사용하고자 한다면 가급적 UTF-8 을 사용하여 인코딩 해라.
- 하지만 한글 사용시 여러가지 문제가 발생할 수 있으니 주의하자.
캐릭터 인코딩 :
언리얼 엔진의 캐릭터 인코딩
언리얼 엔진에 사용되는 캐릭터 인코딩을 검토합니다.
dev.epicgames.com
FName :
언리얼 엔진의 FName
언리얼 엔진에서 FName 제작, 변환 및 비교를 위한 참고 자료입니다.
dev.epicgames.com
FString :
언리얼 엔진의 FString
언리얼 엔진에서 FString 제작, 변환 및 비교를 위한 참고 자료입니다.
dev.epicgames.com
[ ✔️문자열 처리 실습 ]
1. 언리얼은 유니코드를 사용해서 문자열 처리를 통일화 시킨다
- 유니코드(UTF-16)를 사용해 문자열 처리를 통일
- 유니코드를 위한 언리얼 표준 캐릭터 타입 : TCHAR
2. 문자열은 "TEXT 매크로"를 사용해 지정
- TEXT 매크로로 감싼 문자열은 TCHAR 배열로 지정됨
- 내부적으로 2Byte 유니코드(UTF-16) 문자열 반환
3. 문자열을 다루는 클래스로 FString을 제공함
- "FString"은 TCHAR 배열을 포함하는 Helper 클래스
[ ✔️FString ]
📍구조 :
- TCHAR 배열을 FString에 넣게 되면, TCHAR 동적 배열로 바뀌는데, 이때 언리얼에서 제공하고 있는 TArray에 보관된다.
- FString에서 포인터 방식을 이용해 데이터를 가져온다. → 동적 배열로 관리되니 문자열을 자르거나 붙이는 작업이 가능해진다.
- FCString 을 통해서 다양한 함수들을 불러와 문자열을 편집한다.
유용한 함수들 :
- FString::Printf
- FString::SanitizeFloat
- FString::FromInt
- FCStirng::Atoi
- FCString::Atof
📍실습_1 : 문자열 탐색
1. TCHAR* 타입으로 데이터 꺼내기 :
일반적으로 String의 경우 내부적으로 봤을 때 const char* 인걸 알 수 있다.
FString의 경우 데이터를 꺼내오면 const TCHAR* 형태로 되어있다.
만약 const를 때서 받아오고 싶다면...아래의 방식으로 받아와주면 된다.
FString String = TEXT("HELLO");
TCHAR* Char = String.GetCharArray().GetData();
2. TCHAR[] 타입으로 데이터 꺼내기 :
배열로 데이터를 꺼내기 위해서 저수준 복사를 진행하는것이 좋다.
TCHAR LogCharArrayWithSize[100];
FCString::Strcpy(LogCharArrayWithSize, LogCharString.Len(), *LogCharString);
// Strcpy(TCHAR * dst, Length, Buffer);
// 어디에? 얼만큼? 어디에서? 의 순서대로 딱딱딱 하면 된다.
3. 문자열 포함 확인 :
int32 Index = LogCharString.Find(TEXT("unreal"), ESearchCase::IgnoreCase);
FString::Find() 함수를 사용하여 특정 문자열을 FString 에 포함되어 있는지 확인하할 수 있다.
두번째 인자로 대소문자 구분 여부를 지정해줄 수 있다.
이 때, 문자열이 존재한다면 해당 문자열이 시작되는 위치의 인덱스 값을 반환한다.
예제에선 원문 "Hello Unreal" 에서 "unreal" 이라는 단어가 존재하는지 확인하고 있고, 문자열에서 "Unreal"문자열이 시작하는 인덱스인 "6"을 반환한다.
4. 문자열 자르기 :
FString EndString = LogCharString.Mid(Index);
FString::Mid() 함수를 사용하여 FString 문자열을 자를 수 있다.
인자로 들어온 인덱스부터 마지막 까지 잘라서 FString 타입으로 반환해준다.
"Hello Unreal" 이 "Unreal" 로 잘려서 EndString에 저장된 것을 확인할 수 있다.
📍실습_2 : 문자열 자르기
bool FString::Split(const FString& InS, FString* LeftS, FString* RightS) const
// 1. 구분 문자열 2. 왼쪽 문자열 3. 오른쪽 문자열
이전 실습에서 사용했던 FString::Mid() 말고도 FString::Split() 함수를 사용하여 문자열을 자를 수 있다.
첫번째 인자로 들어온 구분 문자열을 기준으로 왼쪽 오른쪽으로 나눠서 각각 두번째, 세번째 인자에 저장해준다.
윈도우 환경에서 소스코드에 한글을 작성했기에 "CP949 (Multibyte String)" 인코딩이 적용되었기에 UTF-16을 사용하는 Unreal과 호환 되지 않음
📍실습_3 : 변환 (int / float → String)
정수형이었던 IntValue 와 실수형이었던 FloatValue 가 FString 타입으로 변환된 것을 확인할 수 있다.
📍실습_4 : 변환 (String → int / float)
[ ✔️FName / FText ]
FString 은 위의 그림과 같이 FName 과 FText로 뻗어 나갈 수 있다.
📍FName :
애셋 관리를 위해 사용되는 문자열 체계
- 문자열 사용에 있어 초경량 시스템을 제공 (가볍고 빠름)
- 대소문자 구분 없음
- 한번 선언되면 변경 불가
- 문자를 표현하는 용도가 아닌 Asset 키 를 지정하는 용도로 사용
- 무엇인가 찾기위한 용도이지 문자열을 처리하기 위한 용도가 아님
- FString으로 변환하여 사용할 수 있는데 대소문자 구분이 없기에 변환과정에서 데이터가 깨질 수 있다.
언리얼 자체에 FName은 글로벌 Pool 자료구조(싱글톤으로 구성)를 자기도 있다.
즉, 문자열 정보는 다른곳에 저장되고 해시되서 다른 값이 저장된다는 것
String이 저장되는 것이 아니라 어떠한 키 값이 저장되기에 용량이 작다.
때문에 Asset을 보관하는데 적합하다.
📍FText :
다국어 지원을 위한 문자열 관리 체계 (별다른 설명 없이 넘어감)
- 일종의 키로 작용
- 별도의 문자열 테이블 정보가 추가로 요구됨
- 게임 빌드 시 자동으로 다양한 국가별 언어로 변환됨
📍실습_1 : FName 대소문자 구분 안함
key1의 경우 대문자를 사용하고 key2의 경우 소문자를 사용했는데 같음 판정을 받았다는 것은 대소문자 구분을 하지 않는다는 것을 증명한다.
📍실습_2 : FName 사용시 주의사항
FName 선언시 FName의 생성자는 내부에 있는 문자열을 Key로 변환하고 해당 Key가 전역 Pool 에 존재하는지 조사한다.
FName의 빈번한 호출은 오버헤드(overhead)를 유발 할 수 있기에 전역 로컬 변수( StaticOnlyOnce )로 사용하거나
반복문 또는 자주 호출되는 함수의 호출 이전에 한번만 선언( SearchInNamePool )해주는게 더 효과적이다.
오버헤드(Overhead) 란?
프로그램의 실행 흐름에서 나타나는 현상중 하나로, 프로그램의 실행흐름 도중에 동떨어진 위치의 코드를 실행시켜야 할 때, 추가적으로 시간, 메모리, 자원이 사용되는 현상이다.
즉, 오버 헤드는 특정 기능을 수행하는데 드는 간접적인 시간, 메모리 등과 같은 자원을 의미한다.
================================
개인 공부 기록용 포스팅입니다.
댓글, 질문 환영해요~!
Unreal Engine Ver : 5.1.1
Refer : Inflearn_이득우의 언리얼 프로그램
================================
'Unreal > Inflearn' 카테고리의 다른 글
Part1.6 언리얼 오브젝트 리플렉션 시스템 Ⅱ⭕ (0) | 2024.04.08 |
---|---|
Part1.5 언리얼 오브젝트 리플렉션 시스템 Ⅰ⭕ (0) | 2024.04.08 |
Part1.4 언리얼 오브젝트 소개 ⭕ (0) | 2024.04.08 |
Part1.2 언리얼 C++ 코딩 표준 ⭕ (0) | 2024.04.06 |
Unreal 초기설정⭕ (0) | 2024.02.21 |