[UE] C++로 UObject 파생 클래스를 인스턴스화 하기, UE에서 관리되는 메모리

라멘커비·2024년 9월 28일
0

Unreal Engine

목록 보기
7/7
post-thumbnail

언리얼 엔진에서 참조 카운트 및 메모리 관리를 받으려면 직접 malloc/free, 또는 new/delete로 생성과 삭제를 하면 안 된다. 자동으로 이뤄지는 메모리 관리를 받기 위해서는 모든 오브젝트의 메모리 할당은 NewObject<>() 또는 SpawnActor<>() 함수를 사용해야 한다.

C++로 UObject 파생 클래스를 인스턴스화 하기

NewObject 함수 사용해서 UObject 파생 모델을 인스턴스화한다. 이 함수는 C++ 클래스 이름만 취하는 것이 아니라 C++ 클래스의 블루프린트 클래스 파생 모델(UClass* 참조)도 필요로 한다. UClass* 참조는 블루프린트에 대한 포인터다.

TSubclassOf, FSoftClassPath

C++ 코드에서 특정 블루프린트의 인스턴스를 인스턴스화하려면 이름을 알아야 하는데 이 이름은 컴파일 후에만 접근할 수 있기 때문에 이름을 알려줄 방법이 필요함. 이를 위해 TSubclassOf 타입의 변수를 사용. 코드 수준에서 하드코딩하지 않을 수 있다. 특정 리소스의 이름을 코드에서 직접 입력하는 것을 원치 않듯이, 파생된 블루프린트 클래스 이름을 하드코딩하는 것도 원치 않는 방식이다.
또는 FStringClassReference(UE4) 멤버를 사용해 처리할 수 있다. UE5에서는 FSoftClassPath임.

예시

둘은 같은 역할을 함.

  • UObject 파생 UClass를 선택할 수 있게 된다.
  • FSoftClassPath는 MetaClass 태그에 파생될 것으로 예상되는 클래스를 입력해주면 된다. MetaClass를 그냥 두면 모든 블루프린트들을 볼 수 있다.
    예시에서는 GameMode 파생된 UCLASS들을 볼 수 있음.

NewObject<>

AActor 클래스 파생 - GetWorld()->SpawnActor<> 사용
UObject 파생 클래스 - NewObject<> 사용

  • SpawnActor, NewObject 사용 모습

NewObject 함수는 객체지향 프로그래밍에서 '팩토리'라고 부르는 디자인 패턴이라고 한다. 오브젝트를 직접 생성하는 대신 팩토리에 원하는 오브젝트의 생성을 요청하는 방식. 팩토리 패턴을 잘 사용하면 생성되는 오브젝트를 추적하는 일이 가능해진다.

UObject 파생 클래스 파괴

메모리 관리 기능의 도움을 받으면 메모리 해체를 잊는 실수를 걱정하지 않아도 된다. 오브젝트를 참조하는 포인터의 수를 기억한다. 참조하는 포인터가 없을 때는 자동으로 즉시 지워지거나, 표시한 후에 다음 차례의 가비지 컬렉션 때 지워진다.
참조 카운트가 0으로 떨어지기 전에 ConditionalBeginDestroy 함수 사용해서 수동으로 메모리에서 해제할 수 있다. ConditionalBeginDestroy() 명령은 메모리 해제 절차를 시작하며, 재정의 가능한 BeginDestroy()와 FinishDestroy() 함수를 호출한다.
(근데 플젝할 때 ConditionalBeginDestroy함수를 사용한 적이 없다... Actor는 Destroy로 삭제하는 부분이 꽤 있다. 발사체, 스포너 등등.)

관리되는 메모리 - 오브젝트 추적을 위해 스마트 포인터 사용

>> TSharedPtr, TWeakPtr, TAutoPtr
delete 호출을 잊는 것을 걱정해서 사용하는 스마트 포인터.

C++ 코드에서 수동으로 UObject 파생이 아닌 오브젝트를 추적하고 삭제하는 상황이라면 TSharedPtr, TSharedRef와 같은 스마트 포인터를 사용. new 키워드를 사용해 동적으로 할당되는 오브젝트를 사용한다면, 이를 참조 카운트를 지원하는 포인터로 감싸서 자동으로 메모리 해제가 일어나도록 할 수 있다.

TSharedPtr 은 모든 커스텀 C++ 오브젝트를 참조 카운트 방식으로 만든다. (UObject는 이미 참조 카운트 방식임. 그 파생 클래스는 TSharedPtr 사용 불가능) 공유 오브젝트에 더 이상 참조가 없을 때 할당 해제된다. 스레드로부터 안전한(참조 카운팅 방식이 atomic하다고 함. 카운트가 0이되어 제거하는 행동을 정확히 한 번만 실행.-> 기본 오브젝트를 별도의 스레드에서 안전하게 조작할 수 있음을 의미.) 참조 카운트 포인터 타입.
TWeakPtr도 참조 카운트 오브젝트를 지원하는데 삭제를 방지할 수 없다는 특징이 있음.
TAutoPtr 스레드로부터 안전하지 않은 공유 포인터.

언리얼의 가비지 컬렉션 시스템과 UPROPERTY

UCLASS의 멤버로 UPROPERTY 같은 오브젝트가 있을 때 블루프린트에서 편집하지 않더라도 UPROPERTY()로 선언해야 한다. 그렇지 않으면 제대로 할당되지 않는다.

profile
일단 시작해보자

0개의 댓글