[Unreal] 첫 번째 멀티플레이어 환경 설정
C++ 클래스의 이해
언리얼 엔진 5가 출시되면서 에픽게임즈는 C++ 헤더 프리뷰(Header Preview)라는 놀라운 검사 도구를 도입했다. 이 도구를 사용하면 블루프린트 클래스가 마치 C++로 작성된 것처럼 검사 결과를 볼 수 있다.
언리얼 엔진에는 개발 중에 파생될 수 있는 세 가지 주요 클래스 타입이 있다.
- UObject: 언리얼 엔진의 기본 클래스이며, 가비지 컬렉션, 네트워킹 지줜, 프로퍼티 및 멤버 함수의 리플렉션 등 언리렁 엔진에서 사용 가능한 대부분의 주요 기능을 제공한다.
- AActor: 에디터 또는 런타임 중에 게임 레벨에 추가할 수 있는 UObject이다. 런타임 중에 추가될 때는 액터가 스폰됐다고 말한다. 또한 AActor는 멀티플레이어 환경에서 네트워킹 중에 복제될 수 있는 기본 타입이며, 동기화가 필요한 모든 컴포넌트의 정보를 제공한다.
- UActorComponent: 액터 또는 액터 자체에 속하는 다른 컴포넌트에 연결할 컴포넌트를 정의하는 기본 클래스다.
또한 다음과 같은 엔티티를 사용하게 된다.
- UStruct: 일반적인 데이터 구조를 생성하는 데 사용되며 특정 클래스에서 확장되지 않는다.
- UEnum: 요소의 열거형을 나타내는 데 사용된다.
클래스 이름이 일부 분자로 시작하는 것을 볼 수 있는데, 이 접두사는 에디터에서 클래스가 사용될 때는 표시되지 않는다. 언리얼 엔진은 클래스 타입을 나타내기 위해 접두사를 사용하며, 주요 접두사는 다음과 같다.
- U: UObject에서 파생된 일반적인 객체에 사용된다.
- A: 액터에서 파생된 객체에 사용되며 레벨에 추가될 수 있다.
- F: FColor 구조체와 같은 일적인 클래스 및 구조체에 사용된다.
- T: TArray 또는 TMap과 같은 템플릿에 사용된다.
- I: 인터페이스에 사용된다.
- E: 열거형에 사용된다.
- B: bool 또는 uint8에 사용된다.
언리얼 엔진 C++ 헤더 분석
우선 #include "Pickup.generated.h" 선언을 볼 수 있다. 이 필수 코드 라인은 언리얼 헤더툴(UHT, Unreal Header Tool)이 자동 생성하며, 엔진에서 코드가 정상 작동하는 데 필요한 매크로를 모두 포함한다.
클래스 생성자는 일반적인 C++ 클래스와 마찬가지로 프로퍼티의 기본값을 설정하는 데 사용되며, 액터 자체에 컴포넌트를 생성하고 추가하는 데오 사용된다.
다음으로, 언리얼 엔진에서는 UCLASS(), GENERATED_BODY(), UPROPERTY(), UFUNCTION()과 같은 매크로를 사용하며, 각각은 명확한 기능을 가지고 있다.
언리얼 엔진 리플렉션 시스템
리플렉션이라는 용어는 프로그램이 런타임에 자신의 구조를 검사할 수 있는 기능을 나타낸다. 이 기능은 매우 유용한 언리얼 엔진의 핵심 기술 중 하나로, 에디터의 디테일 패널, 직렬화, 가비지 컬렉션, 네트워크 복제, 블루프린트와 C++ 간의 통신 같은 다양한 시스템을 지원한다.
C++에서는 리플렉션을 기본적으로 지원하지 않으므로, 에픽게임즈는 언리얼 엔진에서 C++ 클래스, 구저체 등의 관련 데이터를 수집, 검사, 변경할 수 있는 자체 시스템을 개발했다.
리플렉션 시스템에서 사용 가능한 기본 마크업 요소는 다음과 같다.
- UCLASS(): UObject에서 파생되는 클래스의 리플렉션 데이터를 생성하는 데 사용된다.
- USTRUCT(): 구조체의 리플렉션 데이터를 생성하는 데 사용된다.
- GENERATED_BODY(): 이 마크업은 해당 타입에 필요한 사용구 코드로 모두 대체된다.
- UPROPERTY(): 관련된 멤버 변수가 블루프린트 접근성이나 네트워크 복제와 같은 추가 기능이 있음을 엔진에 알리는 데 시용된다.
- UFUNCTION(): 확장된 블루프린트 클래스에서 이 함수를 호출하거나 블루프린트 자체에서 함수를 재정의할 수 있다.
리플렉션 시스템은 가비지 컬렉터에서도 사용되므로 메모리 관리를 걱정할 필요가 없다.
메모리 관리와 가비지 컬렉션
C++에서는 가비지 컬렉션을 기본적으로 구현하지 않으므로, 언리얼 엔진이 자체 시스템을 구현한다. 프로그래머는 단지 객체의 참조가 유효한지 확인만 하면 된다. 클래스에 가비지 컬렉션을 활성화하려면 UObject에서 상속돼야 한다. 그러면 시스템은 가비지 컬렉션되지 않아야 할 객체 리스트(루트root 라고도함)를 유지한다. 객체가 루트에 리스트돼 있는 한 객체는 삭제되지 않고 보존된다. 하지만 이 리스트에서 제거된다며, 다음에 가비지 컬렉터가 호출될 떄 메모리에서 삭제된다.