본문 바로가기

공부/이득우의 언리얼 프로그래밍

[Study] Part 1 - 언리얼 컨테이너 라이브러리 II - 구조체와 Map (11/15)

728x90
반응형

 

 

 

  • 정리
    • 구조체와 언리얼 컨테이너 라이브러리
      1. TArray, TSet, TMap 컨테이너 라이브러리 내부 구조와 활용 방법
      2. 언리얼 구조체의 선언 방법
      3. TSet과 TMap에서 언리얼 구조체를 사용하기 위해 필요한 함수의 선언과 구현 방법

 

 

 

 

  • 언리얼 구조체 UStruct
    • 데이터 저장/전송에 특화된 가벼운 객체
    • 대부분 GENERATED_BODY매크로를 선언해준다.
      • 리플렉션, 직렬화와 같은 유용한 기능을 지원함
      • GENERATED_BODY를 선언한 구조체는 USriptStruct클래스로 구현됨
      • 이 경우 제한적으로 리플렉션을 지원함
        • 속성 UPROPERTY만 선언할 수 있고 함수 UFUNCTION은 선언할 수 없음
    • 언리얼 엔진의 구조체 이름은 F로 시작함
      • 대부분 힙 메모리 할당(포인터 연산)없이 스택 내 데이터로 사용됨
      • NewObject API를 사용할 수 없음

 

 

 

  • 언리얼 리플렉션 관련 계층 구조

리플렉션에 관련된 언리얼 오브젝트의 계층 구조

 

 

	const int32 StudentNum = 300;
	for (int32 ix = 1; ix <= StudentNum; ++ix)
	{
		StudentsData.Emplace(FStudentData(MakeRandomName(), ix));  // Add() 보다는 Emplace()
	}

	TArray<FString> AllStudentsNames;  // TArray
	Algo::Transform(StudentsData, AllStudentsNames, // 알고리즘 라이브러리 사용해서 배열을 복사
		[](const FStudentData& Val)
		{
			return Val.Name;
		}
	);

	UE_LOG(LogTemp, Log, TEXT("모든 학생 이름의 수 : %d"), AllStudentsNames.Num());  // Num() 함수를 통해서 전체 갯수를 출력 / 배열이라 중복 가능

	TSet<FString> AllUniqueNames;  // TSet
	Algo::Transform(StudentsData, AllUniqueNames, // 알고리즘 라이브러리 사용해서 배열을 복사
		[](const FStudentData& Val)
		{
			return Val.Name;
		}
	);
	
	UE_LOG(LogTemp, Log, TEXT("중복 없는 학생 이름의 수 : %d"), AllUniqueNames.Num());  // Num() 함수를 통해서 전체 갯수를 출력 / Set이라 중복이 없음
  • 구조체에서 값을 복사하는 또다른 방법 / TArray / TSet

 

 

 

	UPROPERTY()
	TArray<TObjectPtr<class UStudent>> Students;
  • MyGameInstance.h
  • 포인터를 관리하게 되는데, TArray에 내부적으로 포인터를 관리하게 되면, 반드시 자동으로 언리얼 엔진이 메모리를 관리할 수 있게 UPROPERTY() 매크로를 붙여줘야 한다.
    • 필수! 주의하자.

 

 

 

객체의 동적 배열 관리를 위한 예제 다이어그램

  • 언리얼 오브젝트 학생의 동적 배열 관리 방법
  • 언리얼 구조체 학생 정보의 동적 배열 관리 방법

 

 

 

 


 

 

 

  • TMap의 특징
    • STL map과 TMap의 비교
      • STL map의 특징
        • STL map은 STL set과 동일하게 이진 트리로 구성되어 있음
        • 정렬은 지원, 메모리 구성이 효율적이지 않으며, 데이터 삭제시 재구축이 일어날 수 있음
        • 모든 자료를 순회하는데 적합하진 않음
      • 언리얼 TMap의 특징
        • 키, 밸류 구성의 튜플(Tuple) 데이터의 TSet 구조로 구현되어 있음
        • 해시테이블 형태로 구축되어 있어 빠른 검색이 가능
        • 동적 배열의 형태로 데이터가 모여있음
        • 데이터 빠르게 순회할 수 있음
        • 데이터는 삭제해도 재구축이 일어나지 않음
        • 비어있는 데이터가 있을 수 있음
        • TMultiMap을 사용하면 중복 데이터를 관리할 수 있음
    • 동작 원리는 STL unordered_map과 유사
    • 키, 밸류 쌍이 필요한 자료구조에 광범위하게 사용됨.
 

언리얼 엔진의 맵 컨테이너 | 언리얼 엔진 5.4 문서 | Epic Developer Community

TMap, 맵은 크게 키 유형과 값 유형, 두 가지로 정의되며, 맵에 하나의 짝으로 저장됩니다.

dev.epicgames.com

 

 

TMap의 내부 구조

  • 전반적인 요소가 TSet과 유사하다.

 

	Algo::Transform(StudentsData, StudentsMap,  // Map
		[](const FStudentData& Val)
		{
			return TPair<int32, FString>(Val.Order, Val.Name);
		}
	);

	UE_LOG(LogTemp, Log, TEXT("순번에 따른 학생 맵의 레코드 수 : %d"), StudentsMap.Num());

	TMap<FString, int32> StudentsMapByUniqueName;  // TMap

	Algo::Transform(StudentsData, StudentsMapByUniqueName,
		[](const FStudentData& Val)
		{
			return TPair<FString, int32>(Val.Name, Val.Order);
		}
	);

	UE_LOG(LogTemp, Log, TEXT("이름에 따른 학생 맵의 레코드 수 : %d"), StudentsMapByUniqueName.Num());

	TMultiMap<FString, int32> StudentMapByName;  // TMultiMap
	Algo::Transform(StudentsData, StudentMapByName,
		[](const FStudentData& Val)
		{
			return TPair<FString, int32>(Val.Name, Val.Order);
		}
	);

	UE_LOG(LogTemp, Log, TEXT("이름에 따른 학생 멀티맵의 레코드 수 : %d"), StudentMapByName.Num());

	const FString TargetName(TEXT("이혜은"));
	TArray<int32> AllOrders;
	StudentMapByName.MultiFind(TargetName, AllOrders);  // MultiFind

	UE_LOG(LogTemp, Log, TEXT("이름이 %s인 학생 수 : %d"), *TargetName, AllOrders.Num());

	TSet<FStudentData> StudentsSet;  // FStudentData를 TSet에 사용하기 위한 방법 예시
	for (int32 ix = 1; ix <= StudentNum; ++ix)
	{
		StudentsSet.Emplace(FStudentData(MakeRandomName(), ix));
	}
  • Map / TMultiMap / MultiFind

 

	bool operator==(const FStudentData& InOther) const
	{
		return Order == InOther.Order;
	}

	friend FORCEINLINE uint32 GetTypeHash(const FStudentData& InStudentData)
	{
		return GetTypeHash(InStudentData.Order);
	}
  • MyGameInstance.h / 커스텀 구조체에 대한 해쉬 데이터를 만들기 위한 오퍼레이터 및 함수들

 

 

 

각 자료구조의 시간복잡도

 

  • TArray와 TMap이 주로 많이 쓰임
    • TArray
      • 간편, 효율적이라서 자주 쓰임. 그러나 검색과 삽입 삭제에 대한 비용이 꽤나 발생한다. 빈틈이 없는 자료구조이다.
      • 가장 높은 접근성능과 순회성능
    • TMap
      • 키와 밸류쌍
      • 중복을 불허한다.
      • 편리하게 자료 검색에 용이

 

 

 

 

 

 

해당 포스트는 인프런의 <이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해>
강의를 수강하고 정리한 내용입니다.
 

이득우의 언리얼 프로그래밍 Part1 - 언리얼 C++의 이해 | 이득우 - 인프런

이득우 | 대기업 현업자들이 수강하는 언리얼 C++ 프로그래밍 전문 과정입니다. 언리얼 엔진 프로그래머라면 게임 개발전에 반드시 알아야 하는 언리얼 C++ 기초에 대해 알려드립니다., [사진] 언...........................

www.inflearn.com

 

 

 

 

 

728x90