C++에서 단순하게 액터를 생성하면 언리얼 에디터에 액터를 배치할 수 있지만, 에디터에서 옵션을 수정하는건 아직 불가능하다.
그걸 가능하게 하기 위해선 리플렉션 시스템에 액터와 변수, 함수를 등록해주어야 한다.
1. 리플렉션 시스템(Reflection System)
- 여러 매크로를 이용해 C++과 언리얼 에디터 간에서 상호적인 작업이 가능하도록 해주는 시스템
2. 매크로
- 전처리기를 통해 매크로에 지정된 코드로 치환해주는 기능
3. 리플렉션 시스템 매크로 종류
- 리플렉션 시스템엔 다양한 매크로 종류가 있으나 오늘은 액터 클래스에서 사용할 만한 매크로만 짚어보겠다.
- UCLASS() : 해당 클래스에서 리플렉션 시스템 작업을 하겠다는 것을 명시하는 매크로.
플래그 미기입 시 기본 속성플래그가 자동으로 입력된다. (Blueprintable, BlueprintType)
- 주요 속성 플래그
- Blueprintable : 블루프린트에서 클래스를 기반으로 새 블루프린트를 생성할 수 있음. 기본 활성화된 플래그.
- NotBlueprintable : 블루프린트에서 클래스를 기반으로 새 블루프린트를 생성할 수 없도록 제한.
- BlueprintType : 블루프린트에서 변수를 만들거나 참조할 수 있음. 주로 UObject 기반 클래스에 사용
- NotBlueprintType : 블루프린에서 변수를 만들거나 참조할 수 없음. - GENERATED_BODY() : UCLASS로 등록 후 리플렉션 데이터를 자동으로 생성하는 매크로
- UPROPERTY() : 바로 다음 기입된 변수를 리플렉션 시스템에 등록시킨다. 플래그를 입력해줘야 에디터상에서
변수가 보여지거나 수정할 수 있다.
- 주요 속성 플래그
- VisibleAnywhere : 에디터에서 값을 볼 수 있지만 수정은 불가능
- VisibleInstanceOnly : 인스턴스에서만 값을 볼 수 있음 (수정 불가)
- VisibleDefaultsOnly : 클래스 디폴트에서만 값을 볼 수 있음 (수정 불가)
- EditAnywhere : 에디터 어디서든 값을 수정할 수 있음
- EditInstanceOnly : 인스턴스에서만 값을 수정 가능
- EditDefaultsOnly : 클래스 디폴트에서만 값을 수정 가능
- BlueprintReadWrite : 블루프린트에서 읽기/쓰기 모두 가능
- BlueprintReadOnly : 블루프린트에서 읽기만 가능
- BlueprintAssignable : 블루프린트에서 이벤트를 바인딩할 수 있음(주로 DECLARE_DYNAMIC_MULTICAST_DELEGATE와 함께 사용)
- BlueprintCallable : 블루프린트에서 호출 가능(주로 함수 관련)
- BlueprintAuthorityOnly : 서버에서만 블루프린트 호출 가능
더보기- Category : 에디터에서 속성을 표시할 카테고리 지정 ( Category = "")DECLARE_DYNAMIC_MULTICAST_DELEGATE :
여러개의 함수를 바인딩할 수 있으며 바인딩된 모든 함수들을 동시에 호출하는 기능을 제공 - UFUNCTION() : 바로 다음 기입된 함수를 리플렉션 시스템에 등록시킨다. 플래그를 입력해줘야 에디터상에서
함수를 호출하거나 사용할 수 있다.
- 주요 속성 플래그
- BlueprintCallable : 블루프린트에서 이 함수를 호출할 수 있음
- BlueprintPure : 블루프린트에서 이 함수의 값만 받을 수 있음
- BlueprintImplementableEvent : C++에서 구현하지 않고 블루프린트에서 구현하는 함수. C++에서 호출 가능
- Category = "" : 에디터상의 세부정보창에서 이 함수를 표시할 섹션을 정의
- 클래스 디폴트 : 클래스의 기본 형태. 컨텐츠 브라우저에 위치한다.
- 클래스 인스턴스 : 클래스 디폴트를 레벨에 배치하면 클래스의 인스턴스가 배치된다.
4. 작성 방법
//예시
UCLASS()
===클래스선언
{
GENERATED_BODY()
protacted:
UPROPETY(EditAnywhere, BlueprintReadWrite, Category = "Components")
int value;
UFUNCTION(BlueprintCallable, Category = "Actions")
void ResetActorPosition();
};

5. 기타 배운 것들
언리얼의 회전축 명칭
- X : Roll
- Y : Pitch
- Z : Yaw
SetActorRotation() 값 입력 시 Y, Z, X 순서
짐벌 락(Gimbal Lock)
- 3축 회전의 약점. 축이 돌고 돌다 모두 겹쳐버리면 축값을 변경해도 한 축으로만 회전한다.
- 이를 보완하기 위한 쿼터니언이라는 방식이 존재한다.
월드 좌표과 로컬 좌표의 차이
- 월드 좌표는 월드 기준 액터 그 자체의 좌표. 로컬 좌표는 각 컴포넌트 기준의 개별 좌표
자동회전을 구현할때 자전은 로컬, 공전은 월드를 사용하는게 적절하다.
Tick()
- 프레임마다 신호를 보낸다.
- 프레임이 각각 다른 환경에선 다른 결과값이 나온다.
DeltaTime
- Tick함수는 항상 Tick(float DaltaTime)으로 사용해야한다.
- Tick함수의 환경별 차이점을 보완하기 위해 프레임당 시간값을
구해주는 엔진 자체의 인자.
- Tick함수에 기반한 트랜스폼 작업에선 항상 변화할 인자에
DeltaTime을 곱해줘야한다. (프레임독립적)
FMath::IsNearlyZero(vari)
- 언리얼에서 제공해주는 기본함수
- 0에 아주 근접하면 0으로 계산하는 함수
- 부동소수는 정확히 떨어지는 값이기 어렵기 때문에
미세한 차이는 무시해주는 기능
PrimaryActorTick.bCanEverTick = true;
-Tick을 켜주는 함수
스케일 지속변화
- 위치와 회전은 엔진에서 상대값으로 처리한다.
그래서 Add를 사용하면 자연스레 현재값에 추가값을 더한다.
- 크기는 엔진에서 절대값으로 처리한다. 그래서 Add를 사용하면 Add값을 현재 크기값으로 덮어버린다.
따라서 지속변화를 주려면 현재값을 직접 불러와서 Add값을 더한 후 입력해줘야한다.
- 절대값으로 처리하는 이유는 크기는 얼마가 더 커졌냐 보단 지금 크기가 얼마냐로 다루는게 더 직관적이기 때문이다.
'게임 개발 공부 > 언리얼엔진' 카테고리의 다른 글
| UE5 | C++ 개발 - Controller 설정 (2) | 2025.01.31 |
|---|---|
| UE5 | C++ 개발 - 움직이는 액터 제작 (3) | 2025.01.23 |
| UE5 | C++개발학습 - 액터클래스 생성 및 컴포넌트 그리고 라이프사이클 (0) | 2025.01.20 |
| UE5 - Git lfs (0) | 2025.01.07 |
| 언리얼 엔진 5 - 캐릭터 애니메이션 (2) | 2024.12.20 |