
Unreal Engine 문서로 언리얼 엔진의 오브젝트를 공부한 내용입니다.
참고 자료
언리얼 엔진의 오브젝트
https://dev.epicgames.com/documentation/ko-kr/unreal-engine/objects-in-unreal-engine
오브젝트란?
- 언리얼 엔진이 설계한 새로운 시스템의 단위 오브젝트(객체)
- 기본 클래스는 UObject이며, 파생된 클래스에 UCLASS 매크로를 붙이면 UObject 처리 시스템이 인식할 수 있다.
UCLASS 매크로
- 해당 매크로를 붙인 클래스를 UObject 시스템에 등록한다.
- 해당 매크로를 붙인 클래스의 생성자에 의해 CDO(Class Default Object)가 생성된다.
-> CDO(Class Default Object)란? 디폴트 템플릿 오브젝트로, 해당 클래스의 기본 값을 가지고 있다.
- GetClass() 함수로 UCLASS 정보를 가져올 수 있다.
- UCLASS 매크로를 붙인 클래스의 변수와 함수 정보를 언리얼에서 인식하도록 하려면 UPROPERTY, UFUNCTION 등 매크로를 붙여주어야 한다.
프로퍼티 및 함수 타입
- UObject는 모든 타입의 함수 또는 멤버 변수를 가질 수 있지만, 언리얼에서 이를 인식하기 위해서는 특정 타입 표준을 준수해야한다. (UPROERPTY, UFUNCTION 매크로 등)
UObject 생성
- C++로 만든 UObject는 엔진 시작 시 초기화되고, 엔진에서 디폴트 생성자를 호출한다. (디폴트 생성자가 없다면 UObject가 컴파일되지 않는다.)
- 생성자는 가벼워야 하기에 해당 메서드 안에서 멤버를 초기화하는 함수 기능을 호출해서는 안된다. (BeginPlay() 메서드에 넣어야 한다.)
- NewObject : 런타임에 새로운 인스턴스를 생성하는 함수이다.
- CreateDefaultSubobject : 컴포넌트 또는 서브오브젝트를 생성하는 함수이다.
- 모든 UObject는 가비지 컬렉션 시스템에 의해 관리되기 때문에 new/delete 연산자를 사용하여 메모리를 수동으로 관리하면 메모리가 손상될 수 있다.
언리얼 헤더 툴
- 가비지 컬렉션, 레퍼런스 업데이트 등 UObject를 통해 제공되는 기능을 활용하려면 UHT(Unreal Header Tool)로 전처리 단계를 실행해 필요한 정보를 대조해야 한다.
헤더 파일 포맷
- 에디터의 New C++ Class 기능을 사용하면 아래처럼 올바른 포맷의 헤더 파일이 구성된다.
#pragma once
#include 'Object.h'
#include 'MyObject.generated.h'
UCLASS()
class MYPROJECT_API UMyObject : public UObject
{
GENERATED_BODY()
};
- #include 'MyObject.generated.h'
-> 마지막 순서로 참조하는 헤더 파일이다.
- UCLASS()
-> 언리얼 엔진에서 언리얼 오브젝트를 인식할 수 있도록 한다. 클래스 지정자를 통해 옵션을 설정할 수 있다.
- class MYPROJECT_API UMyObject
-> UMyObject 클래스를 다른 모듈에서도 사용할 수 있도록 MYPROJECT_API를 붙여준다.
- GENERATED_BODY()
-> 엔진에 필요한 인프라를 지원하기 위해 클래스를 구성한다. (모든 UCLASS와 USTRUCT에 필요하다.)
오브젝트 업데이트
- Actor나 ActorComponent는 Tick 함수가 있지만, UObject 기반 클래스에는 기본적으로 Tick 기능이 없다.
-> FTickableGameObject를 상속받아 Tick 함수를 구현해야한다.
오브젝트 파괴
- 오브젝트가 더이상 사용되지 않을 때 가비지 컬렉션 시스템이 자동으로 오브젝트를 파괴한다.
- MarkPendingKill() 함수를 통해 해당 오브젝트에 대한 모든 포인터를 NULL로 설정할 수 있다. (다음 가비지 컬렉션 패스에서 해당 오브젝트가 지워질 수 있도록 한다.)
-> MarkPendingKiil() 함수는 MarkAsGarbage() 함수로 대체되었다.
-> gc.PendingKillEnabled = true 인 경우 PendingKill로 표시된 오브젝트는 자동으로 null이 되고, 가비지 컬렉터에 의해 삭제된다.
- 강한 참조가 있으면 UObject가 가비지 컬렉터에 의해 지워지지 않고 유지된다.
-> 퍼포먼스가 중요한 경우, 강한 참조를 쓰고 있는 레퍼런스를 약한 참조로 변경하거나 프로그래머가 수동으로 삭제하는 일반 포인터를 사용해야 한다.
- IsValid() 함수를 사용하여 객체가 유효한지 확인하는 대신, 객체가 파괴되기 전에 OnDestroy() 메서드 안에서 nullptr로 설정하는 것을 권장한다.
- MarkGarbage()는 오브젝트 파괴 예정이라는 플래그를 표시하지만 모든 레퍼런스가 해제될 때까지 실제로 가비지 컬렉션되지 않습니다.
- 이전에는 MarkPendingKill() 함수를 사용하여 비용이 높은 오브젝트를 가비지 컬렉션하도록 강제할 수 있었지만, 이제는 유효하지 않다.
- nullptr에 대한 기존 검사는 IsValid() 함수 호출을 권장한다.