본문으로 건너뛰기

안동민 개발노트

본문 시작

AActor와 UObject의 차이점

UObject와 AActor의 수명·월드 배치·컴포넌트·복제 차이를 비교하고 생성 API를 올바르게 선택합니다.

지난 절에서 리플렉션 시스템과 핵심 매크로를 익혔다면, 이제 객체 시스템의 뼈대로 내려가야 합니다.

이번 절은 언리얼 C++에서 가장 자주 만나는 기본 클래스, UObject와 AActor를 비교합니다.

두 클래스의 경계를 명확히 이해해야 설계 실수를 줄일 수 있습니다.


UObject: 언리얼 객체 시스템의 기반

먼저 UObject를 정리하겠습니다.

UObject는 언리얼의 리플렉션 객체 시스템을 이루는 기본 클래스입니다. 일반 C++ 클래스나 값 타입 구조체까지 모두 UObject를 상속하는 것은 아닙니다.

언리얼 엔진에서 객체라고 불리는 거의 모든 것(액터, 컴포넌트, 에셋, 게임 모드 등)은 직간접적으로 UObject를 상속받습니다.

UObject가 담당하는 핵심적인 역할들은 다음과 같습니다.

  • 리플렉션 시스템 통합: UObject는 앞서 배운 UCLASS, UPROPERTY, UFUNCTION 매크로를 통해 언리얼 엔진의 리플렉션 시스템에 통합됩니다. 에디터 노출과 블루프린트 접근, 직렬화에 참여할 수 있지만 실제 허용 범위는 각 타입과 지정자에 따라 다릅니다.
  • 가비지 컬렉션(Garbage Collection) 관리: UObject는 언리얼의 가비지 컬렉터가 수명 주기를 관리합니다. GC가 추적하는 강한 참조 그래프에서 루트로부터 도달할 수 없는 객체는 회수 대상이 됩니다. 임의의 C++ 포인터를 보관하는 것만으로 생존이 보장되지는 않습니다.
  • 직렬화(Serialization): UObject는 자신과 자신의 속성들을 저장하고 불러올 수 있는 직렬화 기능을 제공합니다. 이는 게임 상태를 저장하거나, 네트워크를 통해 객체 데이터를 전송할 때 매우 유용합니다.
  • 에디터 통합: UObject 기반의 객체들은 언리얼 에디터에 통합되어 콘텐츠 브라우저에 표시되거나, 디테일 패널에서 속성을 편집할 수 있게 됩니다.
  • 이름 관리 및 참조: UObject의 이름은 같은 Outer 안에서 구분되며, 다른 UObject들을 강력하게 참조할 수 있는 메커니즘을 제공합니다.

간단히 말해, UObject는 언리얼 엔진의 스마트한 객체 시스템에 편입되어 엔진의 다양한 관리 기능(메모리, 직렬화, 반사 등)의 혜택을 받을 수 있도록 해주는 최소 단위의 클래스입니다.

월드에 배치하지 않더라도 개별 객체의 정체성과 엔진의 수명 관리가 필요하면 UObject 계열을 선택할 수 있습니다. 단순 값 데이터에는 USTRUCT나 일반 C++ 구조체가 더 적합할 수 있습니다.


AActor: 월드에 존재할 수 있는 모든 것

그렇다면 AActor는 무엇일까요?

AActor는 이름에서 알 수 있듯이, 언리얼 엔진의 3D 게임 월드(Level)에 배치될 수 있는 모든 객체의 기본 클래스입니다.

즉, 여러분이 게임 화면에서 보거나 상호작용할 수 있는 거의 모든 것들(캐릭터, 카메라, 라이트, 스폰 지점, 트리, 건물 등)은 AActor를 상속받습니다.

AActor는 UObject를 상속받습니다.

이는 AActor가 UObject의 모든 기능을 그대로 물려받는다는 의미입니다.

즉, AActor도 가비지 컬렉션의 대상이 되고, 직렬화되며, 에디터에 노출됩니다.

하지만 AActor는 UObject에는 없는 추가적인 중요한 기능들을 제공합니다.

  • 변환(Transform) 정보: 액터의 위치(Location), 회전(Rotation), 크기(Scale)는 루트 USceneComponent의 트랜스폼을 통해 표현됩니다. AActor 자체가 이 값을 저장하는 것은 아닙니다.
  • 컴포넌트(Components) 컨테이너: AActor는 여러 UActorComponent를 부착해 기능을 확장하는 컨테이너입니다. StaticMeshComponent(시각 요소), CapsuleComponent(충돌), MovementComponent(이동)처럼 역할을 분리해 조합하면 복잡한 액터도 구조적으로 관리할 수 있습니다.
  • 수명 주기 관리: AActor는 BeginPlay(), Tick(), EndPlay() 등 게임 월드 내에서의 특정 이벤트 발생 시 호출되는 중요한 수명 주기 함수들을 가집니다. 여러분은 이 함수들을 오버라이드(Override)하여 액터의 동작을 정의하게 됩니다.
  • 네트워크 복제(Networking Replication): 멀티플레이어 게임을 만들 때, AActor는 네트워크를 통해 자신의 상태를 클라이언트들에게 복제하는 기능을 제공합니다.
  • 콜리전(Collision) 및 물리 시뮬레이션: UPrimitiveComponent 계열의 컴포넌트와 충돌·물리 설정을 통해 충돌 감지와 물리 시뮬레이션에 참여합니다.

생성과 수명 선택

생성하려는 대상과 수명 관리

같은 UObject 계열이어도 생성 맥락과 월드 등록 경로가 다릅니다.

생성하려는 대상과 수명 관리
생성 상황생성·등록 경로수명에서 확인할 점
일반 객체NewObject<T>(Outer)GC가 추적하는 강한 참조를 유지할 위치
기본 컴포넌트생성자에서 CreateDefaultSubobject<T>()액터의 기본 구성; 씬 컴포넌트 부착 관계는 별도 설정
동적 컴포넌트NewObject<T>(Owner) 후 RegisterComponent()등록과 공간 부착은 별개; 소유 액터와 정리 시점 확인
런타임 액터월드의 SpawnActor<T>()Destroy 후 IsValid 등으로 유효성 확인; 직접 delete하지 않음
일반 객체
생성·등록 경로: NewObject<T>(Outer)
수명에서 확인할 점: GC가 추적하는 강한 참조를 유지할 위치
기본 컴포넌트
생성·등록 경로: 생성자에서 CreateDefaultSubobject<T>()
수명에서 확인할 점: 액터의 기본 구성; 씬 컴포넌트 부착 관계는 별도 설정
동적 컴포넌트
생성·등록 경로: NewObject<T>(Owner) 후 RegisterComponent()
수명에서 확인할 점: 등록과 공간 부착은 별개; 소유 액터와 정리 시점 확인
런타임 액터
생성·등록 경로: 월드의 SpawnActor<T>()
수명에서 확인할 점: Destroy 후 IsValid 등으로 유효성 확인; 직접 delete하지 않음

Tick, 이동, 복제와 충돌은 상속만으로 모두 켜지지 않습니다. 필요한 컴포넌트와 각 기능의 설정을 확인합니다.

지속할 UObject 참조를 멤버에 둘 때는 도달 가능한 객체 안의 UPROPERTY() TObjectPtr<T>처럼 GC가 추적하는 강한 참조를 사용합니다. TObjectPtr만 붙이거나 Outer만 지정하는 것은 같은 보장이 아닙니다.

자주 발생하는 오해

  • UObject도 월드 위치를 가진다: 아닙니다. 월드 트랜스폼이 필요하면 AActor 또는 USceneComponent 기반으로 설계해야 합니다.
  • AActor는 delete로 정리한다: 아닙니다. 언리얼 수명주기(Destroy, GC)에 맞춰 정리해야 하며 수동 delete는 사용하지 않습니다.
  • 복제는 아무 클래스에서나 자동 동작한다: 네트워크 복제는 기본적으로 AActor(및 관련 컴포넌트) 경로에서 설계하는 것이 표준입니다.

게임 인스턴스나 월드 수명에 붙는 관리자는 해당 Subsystem 계열도 검토합니다. Subsystem은 액터 배치를 대신하는 타입이 아니라 엔진이 정해진 수명에 맞춰 생성·정리하는 UObject 계열입니다.

언제 무엇을 사용할까?

  • AActor를 상속받을 때
    • 게임 월드에 시각적으로 배치되어야 하는 오브젝트 (예: 캐릭터, 건물, 무기, 차량, 조명).
    • 3D 공간에서 위치, 회전, 스케일 정보를 가져야 하는 오브젝트.
    • 다른 컴포넌트를 부착하여 복합적인 기능을 수행해야 하는 오브젝트.
    • 특정 게임 이벤트(예: 충돌, 트리거)에 반응해야 하는 오브젝트.
  • UObject를 상속받을 때
    • 게임 월드에 직접 배치될 필요는 없지만, 엔진의 가비지 컬렉션이나 직렬화의 혜택을 받고 싶은 데이터 컨테이너.
    • 특정 시스템의 관리자 클래스 (예: 인벤토리 관리자, 퀘스트 관리자).
    • 특정 UI 위젯의 데이터 모델.
    • 값 구조체로 충분하지 않고 객체 참조가 필요한 블루프린트 데이터.
    • UActorComponent를 상속받지 않는 순수 논리적 컴포넌트.

다음 절에서는 AActor를 상속하는 C++ 클래스를 생성하고 블루프린트로 확장합니다.