[UE4 C++] 액터(Actor) 설계
액터를 이루는 요소
- 이름: 여러 액터가 같은 이름 가질 수 있음
- 유형: 게임플레이에서 수행할 액터의 역할 의미. 액터의 클래스 이름.
- 트랜스폼: 액터는 반드시 월드에 존재해야 하므로 액터는 항상 트랜스폼이 부여됨.
- 프로퍼티: 액터에 설정된 속성 값. 액터 유형에 따라 서로 다른 속성 제공. 속성 값을 디테일 윈도우에서 편집해 같은 유형의 액터들이 서로 다른일을 하게 만들 수 있다.
- 게임 로직: 액터에 특정 상황 발생할 때 대응할 구체적 행동 명령 위한 프로그래밍 코드. 언리얼 엔진은 블루프린트와 C++ 두가지 언어 지원.
컴포넌트(Component)
액터의 주요 기능은 시각적/물리적 기능, 움직임으로 나눠진다.
액터를 설계할 때 이런 다양한 기능을 규격화 하고 액터가 이들을 조합할 수 있도록 설계했는데,
이러한 규격화된 기능을 컴포넌트라 한다.
-주요 컴포넌트
- 스태틱메시 컴포넌트 : 애니메이션X 모델링 애셋. 주로 배경 물체에 사용
- 스켈레탈메시 컴포넌트 : 애니메이션O 모델링 애셋. 주로 캐릭터에 사용.
- 콜리전 컴포넌트 : 구/박스/캡슐로 지정한 영역에 물리적 기능을 설정하기 위한 모듈. 시각적 기능 X.
- 카메라 컴포넌트 : 월드에서 보여지는 현재 상황을 플레이어의 모니터 화면에 출력.
- 오디오 컴포넌트 : 월드에서 소리를 발생시키는 기능.
- 파티클 시스템 컴포넌트 : 파티클 시스템으로 설계된 이펙트를 화면에 보여주는 기능.
- 라이트 컴포넌트 : 전구,헤드라이트 등과 같이 물체에 광원효과 부여.
- 무브먼트 컴포넌트 : 물체에 특정한 움직임 부여.
- 루트 컴포넌트 : 액터는 여러개의 컴포넌트를 가질 수 있고, 그중 대표하는 하나의 컴포넌트를 반드시 지정해야 한다.
RootComponent = Body; // 루트 컴포넌트 지정
Water->SetupAttachment(Body); // 루트 컴포넌트의 자식이 되도록 -> 계층구조
액터 클래스 C++ 설계
예를 들어 액터가 2개의 스태틱메시 컴포넌트를 가지려면,
- 기본적으로 헤더 파일에 선언된 CoreMinimal.h 파일을 EngineMinimal.h 파일로 변경해서 액터 클래스가 UStaticMeshComponent 클래스 정보를 참조할 수 있도록 설정
- 액터 클래스의 멤버 변수로 두 개의 UStaticMeshComponent 클래스의 포인터를 선언
언리얼 엔진은 객체가 더 이상 사용되지 않으면 할당된 메모리를 자동으로 소멸시키는 기능을 제공.
언리얼 실행 환경(런타임)이 우리가 선언한 객체를 자동으로 관리하게 만들려면 코드에서 UPROPERTY() 매크로를 추가해야 한다.
- UPROPERTY 매크로와 언리얼 오브젝트
자동으로 메모리를 관리할 수 있는 UPROPERTY 매크로는 언리얼 오브젝트라는 특별한 객체에만 사용 가능하다.
언리얼 오브젝트는 언리얼 실행 환경에 의해 관리되는 C++ 객체. 콘텐츠를 구성하는 객체들은 모두 언리얼 객체.
C++ 클래스가 언리얼 오브젝트 클래스가 되려면 클래스 선언에 언리얼 엔진이 정의한 특별한 매크로와 규칙을 부여해야 한다.
- 언리얼 오브젝트 클래스 규칙
- 클래스 선언 매크로 : 해당 클래스가 언리얼 오브젝트임을 선언. 클래스 선언 윗줄에 UCLASS 매크로 선언.
클래스 내부에는 GENERATED_BODY 매크로 선언. - 클래스 이름 접두사 : 언리얼 오브젝트는 항상 규칙에 맞게 접두사가 붙어야 한다.
A는 액터 클래스에 사용 --> 예) 분수대 액터 AFountain
U는 액터가 아닌 클래스에 사용 --> 예) 액터 구성요소 스태틱메시 컴포넌트 UStaticMeshComponent - generated.h 헤더 파일 : 언리얼 오브젝트 선언의 마지막 #include 구문에 이 헤더파일 반드시 선언해야 한다.
- 외부 모듈에의 공개 여부 : '모듈명_API' 키워드를 클래스 선언 앞에 추가. 이 키워드가 없으면 다른 모듈에서 해당 객체에 접근 불가.
- 액터의 구축은 클래스의 생성자 코드에서 진행. 언리얼엔진은 생성자 코드에서 컴포넌트를 생성하는 용도로 new가 아닌 CreateDefaultSubobject API라는 특별한 함수를 제공.
Body = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BODY"));
- CreateDefaultSubobject API에 사용하는 문자열 값은 액터에 속한 컴포넌트를 구별하기 위한 Hash 값 생성에 사용. 따라서 다른 컴포넌트와 중복되지 않는 값을 지정해야 한다.
- TEXT 매크로 : 언리얼엔진은 문자열 생성할 때 모든 플랫폼에서 2바이트 문자열 체계를 동일하게 유지시키는 TEXT라는 매크로를 제공.
- 액터와 에디터 연동
C++ 클래스 액터의 컴포넌트나 속성을 언리얼 에디터에서 바꿀 수 있게 하기 위해서는
UPROPERTY 매크로 안에 키워드를 추가하면 된다.
- VisibleAnywhere : 에디터에서 해당 속성 값은 편집하지 못하고 읽을 수만 있다.
객체 유형에 이 키워드를 사용하면 객체를 볼 수 있지만, 해당 객체를 다른 객체로 변경할 수는 없다. (예를 들어 스태틱메시 컴포넌트를 다른 컴포넌트로 변경 X)
값 유형, 객체 유형 모두 이 키워드를 사용해 해당 속성의 데이터를 변경할 수 없다는 점은 동일하지만,
객체 유형의 경우 객체에 속한 속성들을 에디터가 편리하게 보여주고 편집할 수 있는 기능을 제공한다. (예를 들어 스태틱 메시 설정) - EditAnywhere : 에디터에서 속성의 데이터를 변경하려면 이 키워드를 사용
- Category=분류명 : 분류명을 지정해 속성값을 분류해 관리할 수 있도록 하는 기능.
UPROPERTY(EditAnywhere, Category=ID)
int32 ID;
- 액터(컴포넌트)의 기본 위치 값 설정하는 방법
액터 생성자에서 컴포넌트에 SetRelativeLocation을 사용하면 컴포넌트 기본 위치 값을 변경할 수 있다.
변경할 위치 값은 언리얼엔진이 제공하는 구조체 FVector를 사용해 전달.
Water->SetRelativeLoation(FVector(0.0f,0.0f,135.0f));
F 접두사는 언리얼 오브젝트와 관련 없는 일반 C++ 클래스 / 구조체를 의미
- 객체 유형과 값 유형
언리얼 오브젝트의 속성 값은
객체를 관리하는 객체 유형 / 값을 관리하는 값 유형 으로 나뉜다.
예 ) 언리얼 오브젝트 클래스의 포인터는 대표적인 객체유형.
- 언리얼 엔진이 제공하는 대표적인 값 유형
- 바이트: uint8
- 정수: int32
- 실수: float
- 문자열: FString, FName
- 구조체: FVector, FRotator, FTransform
이 값 유형들로 클래스 멤버 변수를 선언하고 UPROPERTY 매크로 설정하면 미리 예약된 기본값이 지정된다.
예를 들어 int32 멤버 변수에 UPROPERTY 매크로 선언하면 이 멤버변수는 무조건 0의 초기값 보장받음.