AActor와 UObject의 차이점
지난 절에서 리플렉션 시스템과 핵심 매크로를 익혔다면, 이제 객체 시스템의 뼈대로 내려가야 합니다.
이번 절은 언리얼 C++에서 가장 자주 만나는 기본 클래스, UObject와 AActor를 비교합니다. 두 클래스의 경계를 명확히 이해해야 설계 실수를 줄일 수 있습니다.
핵심 비교 흐름: UObject 기반 공통 엔진 기능 위에 AActor가 월드 배치/트랜스폼/컴포넌트/복제 기능을 확장하고, 생성 API도 NewObject<>와 SpawnActor<>로 나뉩니다.
UObject: 언리얼 객체 시스템의 심장
먼저 UObject를 정리하겠습니다. UObject는 언리얼 엔진의 모든 객체 지향 프로그래밍의 가장 기본적인 조상 클래스입니다. 언리얼 엔진에서 객체라고 불리는 거의 모든 것(액터, 컴포넌트, 에셋, 게임 모드 등)은 직간접적으로 UObject를 상속받습니다. UObject가 담당하는 핵심적인 역할들은 다음과 같습니다.
- 리플렉션 시스템 통합:
UObject는 앞서 배운UCLASS,UPROPERTY,UFUNCTION매크로를 통해 언리얼 엔진의 리플렉션 시스템에 통합됩니다. 덕분에UObject를 상속받은 모든 클래스는 에디터에서 속성을 조작하고, 블루프린트와 연동되며, 저장 및 로드될 수 있습니다. - 가비지 컬렉션(Garbage Collection) 관리:
UObject는 언리얼의 가비지 컬렉터가 수명 주기를 관리합니다. 참조가 끊긴 객체는 엔진이 자동으로 회수하므로 메모리 누수 위험을 줄일 수 있고, 개발자는 수동 해제 부담을 크게 덜 수 있습니다. - 직렬화(Serialization):
UObject는 자신과 자신의 속성들을 저장하고 불러올 수 있는 직렬화 기능을 제공합니다. 이는 게임 상태를 저장하거나, 네트워크를 통해 객체 데이터를 전송할 때 매우 유용합니다. - 에디터 통합:
UObject기반의 객체들은 언리얼 에디터에 통합되어 콘텐츠 브라우저에 표시되거나, 디테일 패널에서 속성을 편집할 수 있게 됩니다. - 이름 관리 및 참조:
UObject는 엔진 내에서 고유한 이름을 가질 수 있으며, 다른UObject들을 강력하게 참조할 수 있는 메커니즘을 제공합니다.
간단히 말해, UObject는 언리얼 엔진의 스마트한 객체 시스템에 편입되어 엔진의 다양한 관리 기능(메모리, 직렬화, 반사 등)의 혜택을 받을 수 있도록 해주는 최소 단위의 클래스입니다. 여러분이 만드는 커스텀 데이터 구조체나 관리자 클래스 등이 게임 월드에 직접 배치되지 않으면서도 엔진의 관리가 필요한 경우, UObject를 상속받아 사용하게 됩니다.
AActor: 월드에 존재할 수 있는 모든 것
그렇다면 AActor는 무엇일까요? AActor는 이름에서 알 수 있듯이, 언리얼 엔진의 3D 게임 월드(Level)에 배치될 수 있는 모든 객체의 기본 클래스입니다. 즉, 여러분이 게임 화면에서 보거나 상호작용할 수 있는 거의 모든 것들(캐릭터, 카메라, 라이트, 스폰 지점, 트리, 건물 등)은 AActor를 상속받습니다.
AActor는 UObject를 상속받습니다. 이는 AActor가 UObject의 모든 기능을 그대로 물려받는다는 의미입니다. 즉, AActor도 가비지 컬렉션의 대상이 되고, 직렬화되며, 에디터에 노출됩니다. 하지만 AActor는 UObject에는 없는 추가적인 중요한 기능들을 제공합니다.
- 변환(Transform) 정보:
AActor는 3D 월드에서 자신의 위치(Location), 회전(Rotation), 크기(Scale) 정보를 가집니다. 이 정보들을 통해 액터가 3D 공간의 어디에 어떻게 존재하는지 정의됩니다. - 컴포넌트(Components) 컨테이너:
AActor는 여러UActorComponent를 부착해 기능을 확장하는 컨테이너입니다.StaticMeshComponent(시각 요소),CapsuleComponent(충돌),MovementComponent(이동)처럼 역할을 분리해 조합하면 복잡한 액터도 구조적으로 관리할 수 있습니다. - 수명 주기 관리:
AActor는BeginPlay(),Tick(),EndPlay()등 게임 월드 내에서의 특정 이벤트 발생 시 호출되는 중요한 수명 주기 함수들을 가집니다. 여러분은 이 함수들을 오버라이드(Override)하여 액터의 동작을 정의하게 됩니다. - 네트워크 복제(Networking Replication): 멀티플레이어 게임을 만들 때,
AActor는 네트워크를 통해 자신의 상태를 클라이언트들에게 복제하는 기능을 제공합니다. - 콜리전(Collision) 및 물리 시뮬레이션: 액터는 자체적으로 또는 컴포넌트를 통해 다른 액터들과의 충돌을 감지하고, 물리 시뮬레이션에 참여할 수 있습니다.
핵심 차이점 요약: 월드에 존재하느냐?
가장 핵심적인 차이점을 한 문장으로 요약하자면 이렇습니다.
UObject: 언리얼 엔진의 객체 시스템에 편입되어 엔진의 관리를 받는 일반적인 객체입니다. 하지만 3D 월드에 직접적으로 배치되거나 시각적으로 나타나지 않습니다.AActor:UObject를 상속받아UObject의 모든 기능을 가지면서, 3D 게임 월드에 배치될 수 있는 특별한 객체입니다. 위치, 회전, 스케일과 같은 변환 정보를 가지며, 컴포넌트들을 통해 다양한 시각적/물리적/논리적 기능을 수행합니다.
| 특징 | UObject | AActor |
|---|---|---|
| 기본 조상 | 언리얼 엔진 모든 객체의 최상위 클래스 | UObject를 상속받음 |
| 월드 존재 | 3D 월드에 직접 배치되지 않음 | 3D 월드에 직접 배치 가능 (위치, 회전, 스케일 가짐) |
| 용도 | 데이터 컨테이너, 관리자, 에셋 등 | 게임 월드 내의 플레이어, 적, 환경 오브젝트, 라이트 등 |
| 컴포넌트 | 가질 수 없음 (정확히는 UActorComponent 아님) | UActorComponent를 상속받는 컴포넌트들을 가질 수 있음 |
| 수명 주기 | 주로 가비지 컬렉터에 의해 관리 | BeginPlay, Tick, EndPlay 등 월드 이벤트와 연동됨 |
UE5 기준 생성/수명주기 판단
실무에서는 무엇을 상속받을지와 함께 어떻게 생성하고 언제 정리되는지를 같이 판단해야 합니다.
UObject생성:NewObject<>()를 사용합니다.UPROPERTY또는TObjectPtr로 참조를 유지하지 않으면 GC 대상이 될 수 있습니다.- 컴포넌트 생성: 생성자에서는
CreateDefaultSubobject<>(), 런타임 동적 생성은NewObject<>()후RegisterComponent()흐름을 사용합니다. AActor생성: 반드시 월드 컨텍스트에서SpawnActor<>()로 생성합니다.Destroy()호출 이후에는 참조가 유효한지 항상 확인해야 합니다.
UObject 계열을 C++ 포인터로만 들고 있으면 언젠가 참조가 끊길 수 있으므로, 오래 유지할 참조는 UPROPERTY 기반으로 선언하는 습관이 안전합니다.
자주 발생하는 오해
UObject도 월드 위치를 가진다: 아닙니다. 월드 트랜스폼이 필요하면AActor또는USceneComponent기반으로 설계해야 합니다.AActor는delete로 정리한다: 아닙니다. 언리얼 수명주기(Destroy, GC)에 맞춰 정리해야 하며 수동delete는 사용하지 않습니다.- 복제는 아무 클래스에서나 자동 동작한다: 네트워크 복제는 기본적으로
AActor(및 관련 컴포넌트) 경로에서 설계하는 것이 표준입니다.
언제 무엇을 사용할까?
-
AActor를 상속받을 때- 게임 월드에 시각적으로 배치되어야 하는 오브젝트 (예: 캐릭터, 건물, 무기, 차량, 조명).
- 3D 공간에서 위치, 회전, 스케일 정보를 가져야 하는 오브젝트.
- 다른 컴포넌트를 부착하여 복합적인 기능을 수행해야 하는 오브젝트.
- 특정 게임 이벤트(예: 충돌, 트리거)에 반응해야 하는 오브젝트.
-
UObject를 상속받을 때- 게임 월드에 직접 배치될 필요는 없지만, 엔진의 가비지 컬렉션이나 직렬화의 혜택을 받고 싶은 데이터 컨테이너.
- 특정 시스템의 관리자 클래스 (예: 인벤토리 관리자, 퀘스트 관리자).
- 특정 UI 위젯의 데이터 모델.
- 블루프린트에서 접근하고 싶은 커스텀 데이터 구조체.
UActorComponent를 상속받지 않는 순수 논리적 컴포넌트.
이러한 이해를 바탕으로 여러분은 언리얼 엔진 프로젝트에서 어떤 상황에 어떤 기본 클래스를 상속받아 사용할지 올바른 결정을 내릴 수 있게 될 것입니다. 다음 절에서는 이 지식을 활용하여 AActor를 상속받는 여러분의 첫 번째 C++ 클래스를 직접 생성하고 코드를 작성하는 실습을 진행할 것입니다. 개념을 실제 코드로 옮겨보는 과정이 훨씬 명확한 이해를 가져다줄 것입니다.