언리얼 컨테이너 라이브러리 - 구조체, Map

Unreal 이론|2024. 8. 20. 17:56

[이득우의 언리얼 프로그래밍 수업의 정리]

 

언리얼 구조체 UStruct

- 데이터 저장/전송에 특화된 가벼운 객체

- 대부분 GENERATED_BODY 매크로 선언

    -> 리플렉션, 직렬화 같은 유용한 기능 지원

    -> 위의 매크로를 선언한 구조체는 UScriptStruct 클래스로 구현됨

    -> 이 경우 제한적으로 리플렉션 지원 (속성 UPROPERTY만 선언, 함수 UFUCTION은 선언x)

언리얼 엔진의 구조체 이름은 F로 시작

-> 대부분 힙 메모리 할당(포인터 연산) 없이 스택 내 데이터로 사용됨.

-> NewObject API 사용할 수 없음

헤더파일에 작성한 FStudentData 구조체.

 

FStudentData라는 구조체를 TArray에 Emplace로 채워넣는다. 대충 이렇게 쓴다

 

STL map

-> STL set과 마찬가지로 이진 트리로 구성됨

-> 메모리 구성 효율적이지 않고 데이터 삭제시 재구축 발생, 모든 자료 순회하는데 적합x

 

TMap

-> 키, 밸류 구성의 Tuple 데이터의 TSet 구조로 구현됨

-> 해시테이블 형태로 빠른 검색 가능

-> 동적 배열 형태로 빠르게 순회 가능, 데이터 삭제시 재구축x

-> TMultiMap 사용해 중복 데이터도 관리 가능

-> TPair<Key, Value>

TMap은 Unreal Object가 없다면 UPROPERTY 안해도 된다

 

언리얼 구조체를 TMap으로 변환하는 로직.

 

람다함수에서 TMap과 구조가 같은 TPair를 사용해 구조체를 TMap으로 변환한다.

 

TSet에 구조체를 집어넣기 위해서는 GetTypeHash함수를 사용해 해시값을 만들어 줘야한다.

요런 느낌

 

그래서 각 자료구조의 시간복잡도는?

  TArray TSet TMap TMultiMap
접근 O(1) O(1) O(1) O(1)
검색 O(N) O(1) O(1) O(1)
삽입 O(N) O(1) O(1) O(1)
삭제 O(N) O(1) O(1) O(1)

 

TArray는

빈틈없는 메모리, 가장 높은 접근 성능, 가장 높은 순회성능

간편하면서도 가장 효율적이라 가장 많이 사용됨.

TSet은

빠른 중복 감지

TMap은

중복x, 키 밸류 관리 -> 가장 쉽게 자료 검색 가능. TArray다음으로 많이 사용된다.

TMultiMap은

중복o, 키 밸류 관리

 

클라이언트의 로컬 컴퓨터의 성능을 최대한 끌어내야하며, 네트워크 부하를 최대한 줄여 각 클라이언트에게 동일한 경험을 주는것이 게임의 과제이니 만큼 상황에 따른 적절한 자료구조를 사용해야 할것 같다.

'Unreal 이론' 카테고리의 다른 글

언리얼 엔진의 메모리 관리  (1) 2024.09.05
언리얼 네트워킹 개요  (3) 2024.09.02
언리얼 컨테이너 라이브러리 - Array, Set  (0) 2024.08.14
언리얼 델리게이트  (0) 2024.08.14
언리얼 컴포지션  (0) 2024.08.13

댓글()

언리얼 컨테이너 라이브러리 - Array, Set

Unreal 이론|2024. 8. 14. 17:36

[이득우의 언리얼 프로그래밍 수업의 정리]

 

언리얼 자체 제작 자료구조 라이브러리 (UCL - Unreal Container Library)

게임 제작에 유용하게 사용되는 라이브러리는 크게 세가지로, TArray, TSet, TMap

 

C++ STL은 표준이라 범용적이고 호환성이 높지만, 많은 기능이 엮여있어 컴파일 오래걸림

언리얼 컨테이너 라이브러리는 언리얼 엔진에 특화, 언리얼 오브젝트 구조 안정적으로 지원, 가벼워 게임제작에 최적!

 

vector -> TArray

set -> TSet

map -> TMap

위의 쌍으로 용도가 비슷하지만 TSet과 TMap은 내부 구현이 좀 다르다

 

1) TArray

-> Dynamic Array 자료구조.

-> 데이터가 순차적으로 모여있어 메모리 효과적 사용, 캐시 효율 높음

-> 맨 끝에 데이터 추가는 가볍지만, 중간 요소 추가나 삭제는 비용 큼

-> 많은 수의 데이터에서 검색 작업이 빈번하다면 TSet이 더 낫다

-> Add보다 Emplace가 효율이 무조건 더 좋다. 가능하면 Emplace 사용

 

2) TSet

-> 해시테이블 형태로 키 데이터가 구축되어 있어 빠른 검색 가능

-> 동적 배열의 형태로 데이터 모여있음

-> TSet의 데이터는 빠르게 순회 가능

-> TSet의 데이터는 삭제해도 재구축 일어나지 않음

-> TSet의 동적 배열에는 비어있는 데이터 있을 수 있음

-> STL set과 활용 방법 다르기 때문에 주의

-> TSet은 중복 없는 데이터 집합 구축하는데 유용 (파이썬의 Set과 유사한듯?)

-> 데이터 추가할 때 비어있는 부분에 빠르게 메꾸는 형태로 데이터 추가

 

  TArray TSet
접근 O(1) O(1)
검색 O(N) O(1)
삽입 O(N) O(1)
삭제 O(N) O(1)

 

위와 같은 시간복잡도를 가지기 때문에,

TArray는 빈틈없는 메모리, 가장 높은 접근 성능과 순회성능을 가지며

TSet은 빠른 중복감지 기능을 가진다 (메모리에 빈틈이 있을 수 있기 때문에 접근, 순회는 효율 낮을 수 있다)

'Unreal 이론' 카테고리의 다른 글

언리얼 네트워킹 개요  (3) 2024.09.02
언리얼 컨테이너 라이브러리 - 구조체, Map  (0) 2024.08.20
언리얼 델리게이트  (0) 2024.08.14
언리얼 컴포지션  (0) 2024.08.13
언리얼 인터페이스  (0) 2024.08.08

댓글()

언리얼 델리게이트

Unreal 이론|2024. 8. 14. 15:22

[이득우의 언리얼 프로그래밍 수업의 정리]

 

강한 결합 vs 느슨한 결합

강한 결합: 클래스들이 서로 의존성을 가지는 경우

느슨한 결합: 실물에 의존하지 말고 추상적 설계에 의존

-> 호텔 출입 카드와 각 호실의 관계를 예로 들었을 때 Card 자체를 Person 클래스 멤버 변수 타입 등으로 정의한다면, Card 클래스가 없다면 Person 클래스를 정의할 수 없으며 코드 수정시 대부분의 코드를 수정해야함

-> 출입 확인을 위해 Card 클래스를 만들었다면 출입에 관련된 추상적인 설계에 의존

-> ICheck 라는 클래스에서 출입 확인만 하는 추상 가상함수를 생성해 Card가 상속받게 함으로써 Person이 Card에 의존하지 않는 느슨한 결합 구조로 설계

-> 이런 설계 구조는 유지 보수를 손쉽게 함

 

하지만 매번 인터페이스 만들기 귀찮다 -> 함수를 오브젝트처럼 관리 -> 델리게이트 활용

 

델리게이트 선언시 고려사항

-> 어떤 데이터를 전달하고 받을것인지, 인자의 수와 각 타입을 설계

(몇개의 인자를 전달할지, 일대일로 전달, 일대다로 전달 등)

-> 프로그래밍 환경설정

(C++ 프로그래밍에서만 사용할지, UFUNCTION으로 지정된 블루프린트 함수와 사용할지)

-> 어떤 함수와 연결할 것인지

(클래스 외부에 설계된 C++ 함수와 연결, 전역에 설계된 정적 함수와 연결, 언리얼 오브젝트의 멤버 함수와 연결(대부분의 경우))

 

선언 매크로

-> DELCARE_{델리게이트 유형}DELEGATE{함수정보}

1) 델리게이트 유형 : 어떤 유형의 델리게이트인지 구상

    - 일대일 형태로 C++만 지원하면 유형은 공란으로 둔다

      DECLARE_DELEGATE

    - 일대다 형태로 C++만 지원하면 MULTICAST 선언

      DECLARE_MULTICAST

    - 일대일 형태로 블루프린트 지원하면 DYNAMIC 선언

      DECLARE_DYNAMIC

    - 일대다 형태로 블루프린트 지원하면 DYNAMIC과 MULTICAST 조합

      DECLARE_DYNAMIC_MULTICAST

2) 함수 정보 : 연동 될 함수 형태를 지정한다

    - 인자 없고 반환값 없음 -> 공란

    - 인자 하나, 반환값 없음 -> OneParam (DECLARE_DELEGATE_OneParam)

    - 인자 셋, 반환값 있음 -> RetVal_ThreeParams (DECLARE_DELEGATE_RetVal_ThreeParams)

    - 파라미터는 최대 9개까지 지원

 

상호 의존성을 최대한 없애야 함

-> 하나의 클래스는 하나의 작업에만 집중하도록 설계

-> 클래스간 서로 헤더를 참조하지 않도록 신경쓸것

 

델리게이트 이름은 보통 맨 앞에 F를 붙이고, 맨 뒤에 Signature를 붙인다.

 

댓글()

언리얼 컴포지션

Unreal 이론|2024. 8. 13. 17:39

[이득우의 언리얼 프로그래밍 수업의 정리]

 

컴포지션이란?

-> 객체 지향 설계에서 상속은 Is-A 관계(부모와 자식간의 관계)

-> 컴포지션은 Has-A 관계(성질이 다른 두 객체에서 어떤 객체가 다른 객체를 소유하는 관계)를 구현하는 설계 방법.

-> 복잡한 기능을 가진 거대한 클래스를 효과적으로 설계

 

모던 객체 설계 기법의 핵심은 상속을 단순화하고, 단순한 기능을 가진 다수의 객체를 조합해 복잡한 객체를 구성하는 것.

-> 이 과정에서 컴포지션을 적극 활용해 복잡한 기능을 가진 객체를 구성

 

하나의 언리얼 오브젝트에는 항상 클래스 기본 오브젝트 CDO가 1대1로 매칭되어있다.

-> 그렇다면 언리얼 오브젝트의 컴포지션은 어떻게 구현하는가?

-> 1) CDO에 미리 언리얼 오브젝트를 생성해 조합(필수적 포함) -> CreateDefaultSubobject() API 사용

-> 2) CDO에 빈 포인터만 넣고 런타임에서 언리얼 오브젝트를 생성해 조합(선택적 포함) -> NewObject API 사용

언리얼 오브젝트를 생성할 때 컴포지션 정보 구축 가능

-> 내가 소유한 언리얼 오브젝트: SubObject

-> 나를 소유한 오브젝트: Outer

 

언리얼 C++가 제공하는 확장 열거형도 사용해 다양한 메타정보 넣고 활용

 

'Unreal 이론' 카테고리의 다른 글

언리얼 컨테이너 라이브러리 - Array, Set  (0) 2024.08.14
언리얼 델리게이트  (0) 2024.08.14
언리얼 인터페이스  (0) 2024.08.08
언리얼 프로퍼티 시스템(리플렉션)  (0) 2024.08.04
언리얼 오브젝트 개념  (0) 2024.08.03

댓글()

언리얼 인터페이스

Unreal 이론|2024. 8. 8. 20:32

[이득우의 언리얼 프로그래밍 수업의 정리]

 

인터페이스: 객체가 반드시 구현해야 할 행동을 지정하는데 활용되는 타입

활용 예시) 월드에 배치되는 모든 오브젝트, 움직이지 않는 오브젝트(Actor), 움직이는 오브젝트(Pawn)

-> 길찾기 시스템을 반드시 사용하며 움직이는 오브젝트 -> INavAgentInterface 사용

- C++은 다중 상속을 지원하지만, 언리얼 C++의 인터페이스를 사용해 축소된 다중상속의 형태로 구현하는 것이 유지보수에 도움

 

[언리얼 인터페이스의 특징]

인터페이스를 생성하면 두 개의 클래스가 생성됨

-> U로 시작하는 타입 클래스(클래스 타입 정보 제공) + I로 시작하는 인터페이스 클래스(실질적 설계 및 구현)

-> 실제로 U타입 클래스에서 작업하진 않음

Java와 C#은 추상 타입으로만 선언할 수 있지만, 언리얼은 인터페이스에도 구현 가능

 

언리얼 C++인터페이스는 추상 타입으로 강제되지 않고, 내부에 기본 함수 구현 가능

-> 모던 객체지향에서 추구하는 방식은 아니지만 편리한 방법으로 사용 가능

 

인터페이스를 상속받았는지 확인하려면 casting 함수 사용

 

'Unreal 이론' 카테고리의 다른 글

언리얼 델리게이트  (0) 2024.08.14
언리얼 컴포지션  (0) 2024.08.13
언리얼 프로퍼티 시스템(리플렉션)  (0) 2024.08.04
언리얼 오브젝트 개념  (0) 2024.08.03
C2338 - 매크로 관련 에러  (0) 2024.08.02

댓글()

언리얼 프로퍼티 시스템(리플렉션)

Unreal 이론|2024. 8. 4. 09:24

[이득우의 언리얼 프로그래밍 수업의 정리]

 

리플렉션 시스템은 프로그램이 자기 자신을 조사하는 기능.

->딱봐도 핵심 기능인 것 같다.

 

C++에선 지원하지 않아 언리얼에서 자체적으로 구축.

리플렉션 시스템이 보였으면 하는 유형이나 프로퍼티에 주석을 달면 Unreal Header Tool (UHT)가 프로젝트를 컴파일 할 때 해당 정보를 수집함.

 

UPROPERTY 매크로로 정의되지 않은 멤버 변수도 같은 클래스에서 사용 가능. 하지만 해당 리플렉션에 의존하는 시스템 전부에 보이지 않는다는것 주의.

(리플렉션 되지 않은 UObject의 포인터 그대로를 저장하면 보통 가비지 콜렉터가 레퍼런스를 확인할 수 없기 때문에 위험한 일. -> 메모리 누수나 nullpointerexception 같은 오류가 발생하는건가? 사용하다 보면 알 수 있을듯.)

-> 언리얼 엔진에서 UPROPERTY로 선언된 포인터의 메모리를 관리해줌. 저 매크로로 정의하지 않는다면 직접 메모리 관리해야함 

 

UHT가 직접 컴파일을 하는것은 아니기 때문에 정교하지 않으므로 너무 복잡한 정의는 읽어들이지 못한다는 단점 존재.

 

언리얼 오브젝트에 지정하여 관리하는

변수는 UPROPERTY, 함수는 UFUNCTION 매크로 사용.

 

이런 오브젝트들은 모두 클래스 정보와 함께하며 클래스를 사용해 자신이 가진 프로퍼티와 함수 정보를 컴파일타임, 런타임에서 조회 가능.

일반 오브젝트와 다르게 언리얼 오브젝트는 NewObject()라는 별도의 API를 사용해 생성.

언리얼 C++ 오브젝트를 생성하고 GetClass(), StaticClass()로 오브젝트를 사용하는 UClass에 정보 가져옴.

 

언리얼 클래스 정보에는 클래스 기본 오브젝트(Class Default Object -> CDO)가 함께 포함되어 있음.

한 클래스로부터 다수의 물체를 생성해 게임 콘텐츠에 배치할 때 일관성 있게 기본 값을 조정하는데 유용하게 사용.

(모듈화를 쉽게 해주는 기능인듯함.)

CDO는 클래스 정보(UClass)로부터 GetDefaultObject() 함수를 사용해 얻는다.

UClass 및 CDO는 엔진 초기화 과정에서 생성되므로 이후 콘텐츠 제작에서 안심하고 사용 가능

 

'Unreal 이론' 카테고리의 다른 글

언리얼 델리게이트  (0) 2024.08.14
언리얼 컴포지션  (0) 2024.08.13
언리얼 인터페이스  (0) 2024.08.08
언리얼 오브젝트 개념  (0) 2024.08.03
C2338 - 매크로 관련 에러  (0) 2024.08.02

댓글()

언리얼 오브젝트 개념

Unreal 이론|2024. 8. 3. 18:35

[이득우의 언리얼 프로그래밍 수업의 정리]

 

모던 객체 지향 설계 원칙

 

유지보수, 유연함, 확장성 향상을 위한 객체 지향 프로그래밍 원칙 - SOLID

Single responsibility principle : 하나의 클래스는 하나의 책임만을 가져야 함

Open/closed principle : 클래스 설계를 변경하지 않고 동작을 확장할 수 있어야 함

Liskov substitution principle : 자식 클래스는 부모 클래스를 대체 사용할 수 있어야 함

Interface segregation principle : 작고 명확한 인터페이스들로 분리해 관리해야 함

Dependency inversion principle : 구현을 배제시킨 상위 정책을 바라보며 설계해야 함

 

게임 규모의 대형화로 모던 객체 지향 설계 도입이 필요해짐

-> C++언어를 매크로를 이용해 확장, 모던 객체 지향 설계 가능하도록 함

 

언리얼 오브젝트

- 새로운 언리얼 엔진만의 객체 규약

- c++ 오브젝트엔 F, 언리얼 오브젝트엔 U 라는 접두사 사용.

UObject 라는 베이스 클래스에서 상속받아 언리얼 오브젝트 구현, UCLASS 매크로를 사용하여 태그하면 UObject 처리 시스템에서 인식.

 

언리얼 오브젝트의 특징

- 클래스 기본 객체(CDO) : 클래스의 기본 값과 타입 정보의 제공

- 리플렉션 : 런타임에서 클래스 정보의 참조 기능

- 인터페이스 : 모던 객체 지향의 언어가 제공하는 인터페이스 제공

- 향상된 열거형

- 델리게이트 : 객체간의 결합을 낮출 수 있는 델리게이트 기능 제공 (나는 C#에서 쓰려다가 이해못해서 안쓴 기능이었다..)

- 가비지컬렉션 : 자동 메모리 관리

- 향상된 구조체 : 리플렉션 가능한 구조체 지원

- 직렬화(Serialization) : 객체 정보를 바이트 스트림으로 저장, 전송, 불러들이는 기능

 

언리얼 오브젝트는 지정된 매크로를 사용해 빌드를 수행하면, 추가 코드가 자동으로 만들어지는 구조를 가짐(UHT)

-> 대규모 게임제작 안정적으로 설계 및 구현 가능

'Unreal 이론' 카테고리의 다른 글

언리얼 델리게이트  (0) 2024.08.14
언리얼 컴포지션  (0) 2024.08.13
언리얼 인터페이스  (0) 2024.08.08
언리얼 프로퍼티 시스템(리플렉션)  (0) 2024.08.04
C2338 - 매크로 관련 에러  (0) 2024.08.02

댓글()

C2338 - 매크로 관련 에러

Unreal 이론|2024. 8. 2. 22:31

c2338 - static_assert failed formatting string must be a const TCHAR array

나는 UE_LOG 매크로를 사용하며 위의 에러를 경험했다.

 

UE5.1 버전에서는 UE_LOG 매크로의 정의가 달라 TCHAR변수를 그냥 넘겨도 에러가 안떳지만, 5.2버전 이후부터는 함수 내부에서만 변수 수정이 가능하도록 const static으로 TCHAR변수를 선언해줘야 사용 가능.

 

또한 UE_LOG 사용을 지양하고 GEngine->AddOnScreenDebugMessage 방식을 사용하도록 권장한다.

 

5.3에서는 세가지 방식을 사용.

 

1) TEXT 매크로

UE_LOG(LogTemp, Log, TEXT("Log Message"));

 

2) FString 객체 사용

FString LogString = TEXT("Log Message");

UE_LOG(LogTemp, Log, LogString);

 

3) 권장 - GEngine 사용

FString LogString = TEXT("Log Message");

 

GEngine->AddOnScreenDebugMessage(

                  0, // Unique message ID (optional)

                  5.0f, // Message duration in seconds

                  FColor::Red, // Message color

                  LogString, // Message text

);

'Unreal 이론' 카테고리의 다른 글

언리얼 델리게이트  (0) 2024.08.14
언리얼 컴포지션  (0) 2024.08.13
언리얼 인터페이스  (0) 2024.08.08
언리얼 프로퍼티 시스템(리플렉션)  (0) 2024.08.04
언리얼 오브젝트 개념  (0) 2024.08.03

댓글()