언리얼 컨테이너 라이브러리
- 언리얼 엔진이 자체 제작해 제공하는 자료구조 라이브러리
- 줄여서 UCL(Unreal Container Library) 라고도 함.
- 언리얼 오브젝트를 안정적으로 지원하며 다수 오브젝트 처리에 유용하게 사용됨.
- 언리얼 C+은 다양한 자료구조 라이브러리를 직접 만들어 제공하고 있음.
- 실제 게임 제작에 유용하게 사용되는 라이브러리로 세 가지를 추천함.
- TArray, TMap, TSet (여기서 T는 Template를 의미
C++ STL과 언리얼 컨테이너 라이브러리의 차의점
- C++ STL은 범용적으로 설계되어 있다.
- C++ STL은 표준이기 때문에 호환성이 높다.
- C++ STL에는 많은 기능이 엮여 있어 컴파일 시간이 오래걸림.
- 언리얼 컨테이너 라이브러리는 언리얼 엔진에 특화되어 있음.
- 언리얼 컨테이너 라이브러리는 언리얼 오브젝트 구조를 안정적으로 지원한다.
- 언리얼 컨터이너 라이브러리는 가볍고 게임 제작에 최적화되어 있음.
따라서 언리얼 엔진으로 작업을 할 때는, 언리얼 컨테이너 라이브러리를 사용해야 한다.
언리얼 C++ 주요 컨테이너 라이브러리
- 두 라이브러리(STL과 언리얼)의 이름과 용도는 유사하지만, 내부적으로 다르게 구현되어 있음.
- vector 와 TArray 는 유사하게 구현돼있음
- set 과 TSet은 용도는 비슷하지만, 다르게 구현돼있음.
- map 과 TMap은 용도는 비슷하지만, 다르게 구현돼있음.
- Container
- TArray : 오브젝트를 숮서대로 담아 효율적으로 관리하는 용도로 사용
- TSet : 중복되지 않는 요소로 구성된 집합을 만드는 용도로 사용
- TMap : 키, 밸류 조합의 레코드를 관리하는 용도로 사용
TArray 개요
- TArray는 가변 배열(Dynamic Array) 자료구조
- STL의 vector와 동작 원리가 유사.
- 게임 제작에는 가변 배열 자료구조를 효과적으로 활용하는 것이 좋음.
- 데이터가 순차적으로 모여있기 때문에 메모리를 효과적으로 사용할 수 있고 캐시 효율이 높다.
- 컴퓨터 사양이 좋아지면서, 캐시 지역성(Locality)으로 인한 성능 향상은 굉장히 중요해짐.
- 임의 데이터의 접근이 빠르고, 고속으로 요소를 순회하는 것이 가능.
- 가변 배열의 단점
- 맨 끝에 데이터를 추가하는 것은 가볍지만, 중간에 요소를 추가하거나 삭제하는 작업은 비용이 큼
- 데이터가 많아질 수록 검색, 삭제, 수정 작업이 느려지기 때문에, 많은 수의 데이터에서 검색 작업이 빈번하게 일어난다면, TArray대신 TSet을 사용하는 것이 좋음.
https://docs.unrealengine.com/5.1/ko/array-containers-in-unreal-engine/
TArray: 언리얼 엔진의 배열
docs.unrealengine.com
언리얼 TArray 문서이다.
여기서
TArray 는 시퀀스이므로, 그 엘리먼트는 잘 정의된 순서를 갖으며, 그 함수를 사용해서 해당 오브젝트와 순서를 결정론적으로 조작하게 됩니다.
이 이야기는 같은 유형을 가지기 때문에 n번째 요소를 가지고 온다 하면, 해당 주소를 가져올수 있다는 뜻이다.
언리얼에서 가장 자주사용하는 자료구조이다.
Add는 복사나 이동을 하면서 만들지만, Emplace는 새로 만들어서 넣게 된다. Emplace가 Add보다 좋은 점은, 복사나 이동 하는 불필요한 절차를 피할 수 있기 때문이다. 따라서 많이 반복되는 For문에서는 Emplace를 사용하는게 좋고, int32나 float처럼 작은 경우에는 Add를 사용해도 퍼포먼스 적으로 문제가 없지만, 큰 유형에서는 Emplace를 사용하는게 좋다.
AddUnique는 뒤에 설명할 자료구조인 TSet을 사용하는게 더 좋기 때문에 추천하지 않는 함수이다.
TArray를 const로 선언하지 않았을 경우 배열 인자 수정이 가능하다.
Find로 가능하지만, 배열을 전부 순환할수도 있기 때문에 자주 사용은 안좋다. 빠르게 많이 찾아야 한다면 TSet을 사용하는게 좋다.
삭제를 하게되면 삭제 후 재정렬을 하기 때문에 무조건 TArray를 사용해야 되는게 아니라면 TSet을 사용하는게 좋다.
복사를 하는것이기 때문에 Emplace가 아닌 Add가 사용된다.
배열을 넣고 빼는 동작을 반복하게 되면 메모리 재할당이 자주 일어나 비용이 발생하기 때문에 삭제한다고 해도 메모리는 바로 해제되지 않는다.
Memcpy를 사용해서 바로 만드는 것도 가능하다.
나머지는 위의 문서를 확인하는게 도움이 된다.
코드
void UMyGameInstance::Init()
{
Super::Init();
const int32 ArrayNum = 10;
TArray<int32> Int32Array;
for (int32 ix = 1; ix <= ArrayNum; ++ix)
{
Int32Array.Add(ix);
//Int32Array.Emplace(ix);
}
// 짝수 제거
Int32Array.RemoveAll
(
[](int32 Val)
{
return Val % 2 == 0;
}
);
// 복구
Int32Array += {2, 4, 6, 8, 10};
TArray<int32> Int32ArrayCompare;
int32 CArray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
// Int32ArrayCompare 에 초기화 하지 않고 생성하고
Int32ArrayCompare.AddUninitialized(ArrayNum);
// Memcpy를 사용해서 빠르게 값을 복사 해준다.
FMemory::Memcpy(Int32ArrayCompare.GetData(), CArray, sizeof(int32) * ArrayNum);
// 비교를 해본다.
ensure(Int32Array == Int32ArrayCompare);
}
이 상태로 실행하면 빨간 글씨 없이 잘 출력이 된다.
처음 짝수만 제거했을 경우이다.
그 다음에 짝수를 넣으면
그 뒤에 추가가 잘 된다.
복사도 문제 없이 가능하다.
int32 Sum = 0;
for (const int32& Int32Elem : Int32Array)
{
Sum += Int32Elem;
}
ensure(Sum == 55);
int32 SumByAlgo = Algo::Accumulate(Int32Array, 0);
ensure(Sum == SumByAlgo);
알고리즘을 제공한다. 보통 하나하나 더하면서 값을 더하겠지만, Accumulate 사용하면 총합을 간단하게 값을 갖고올 수 있다.
'Unreal' 카테고리의 다른 글
7-3 언리얼 컨테이너 라이브러리 - 구조체 (0) | 2023.11.22 |
---|---|
7-2. 언리얼 컨테이너 라이브러리 - TSet (1) | 2023.10.16 |
6. Delegate - 2 (0) | 2023.10.03 |
6. Delegate - 1 (0) | 2023.09.20 |
5. 컴포지션 (0) | 2023.09.11 |