Dev./UE 언리얼 엔진
[TIL_250127] [스파르타코딩클럽 후기] C++와 Unreal Engine으로 3D 게임 개발 - 리플렉션 시스템 이해하기!
raindrovvv
2025. 1. 27. 21:13
💭회고
설 연휴임에도 불구하고 공부를 했다😂😂
연휴라고 하면 보통 편하게 쉬기 마련이지만,
스파르타코딩클럽 언리얼 과정 중 [C++와 Unreal Engine으로 3D 게임 개발] 강의를 보며,
나름의 긴장감을 유지하면서 공부할 수 있었다!
집중이 잘되지 않았지만, 그래도 많은 내용을 공부할 수 있었다. 특히 리플렉션 시스템과 매크로에 대해 이해하는 데 많은 도움이 되었다. UCLASS(), UPROPERTY(), UFUNCTION() 매크로의 사용법을 정리하면서 에디터와 블루프린트, C++ 간의 상호작용을 보다 명확하게 이해하게 되었다.
언리얼 엔진의 리플렉션 시스템을 적극적으로 활용하면, 메쉬 설정, 머터리얼 설정 등을 보이게 처리해 작업 시 훨씬 편리해진다는 점을 알게 되었다.
스파르타코딩클럽 덕분에 설 연휴 동안에도 유익한 시간을 보낼 수 있었다! 앞으로도 더 많은 것을 배우고 성장해 나갈 생각이다🤗😁🤗
코드카타
🗺️마인드맵
📒학습 내용
UCLASS() 매크로
UCLASS() 매크로는 클래스를 리플렉션 시스템에 등록하고 추가적인 옵션(지정자)을 설정할 수 있다.
기본 동작
- 옵션이 없을 경우, 블루프린트에서 상속 및 변수로 참조가 가능하게 등록
- UCLASS() = UCLASS(Blueprintable, BlueprintType)
주요 태그
- Blueprintable: 블루프린트에서 상속 가능.
- NotBlueprintable: 블루프린트에서 상속 불가.
- BlueprintType: 블루프린트에서 변수나 참조로 사용 가능 (상속 불가).
필요에 따라 지정자 조합으로 클래스와 블루프린트의 상호작용 방식을 명시할 수 있다.
UPROPERTY() 매크로
UPROPERTY()는 C++ 코드에서 변수에 메타데이터를 추가하고, 이를 언리얼 에디터와 엔진에 통합할 수 있게 하는 데 사용된다. 리플렉션 시스템(Reflection System)을 기반으로 하며, 변수의 특성을 정의하거나 에디터에서 노출할 때 중요한 역할을 한다. (일반 변수로는 할 수 없는 기능)
만약 UPROPERTY()만 있고, 추가 지정자를 하나도 주지 않는다면?
- 리플렉션 시스템에는 등록되지만, 에디터나 블루프린트에 노출되지는 않는다.
- “엔진이 변수의 존재는 알고 있지만, 외부에서는 보이지 않게 숨겨둔 상태”라고 보면 된다.
- 리플렉션에 등록만 되어 있어도 가비지 컬렉션(메모리 관리)과 직렬화(세이브/로드) 같은 엔진 내부 기능이 작동할 수 있다.
주요 태그
에디터 노출 관련
- VisibleAnywhere: 에디터에서 읽기만 가능.
- EditAnywhere: 에디터에서 값을 수정할 수 있음.
- EditDefaultsOnly: 디폴트 값만 수정 가능.
- EditInstanceOnly: 인스턴스 값만 수정 가능.
- VisibleDefaultsOnly: 디폴트 값만 읽기 가능.
블루프린트 관련
- BlueprintReadWrite: 블루프린트에서 읽기(Getter)/쓰기(Setter) 가능.
- BlueprintReadOnly: 블루프린트에서 읽기만 가능.
- BlueprintAssignable: 블루프린트에서 이벤트로 바인딩 가능.
카테고리 설정
- 여러 변수를 비슷한 카테고리 안에 묶으면 디테일 패널에서 정리되어 보임.
- Category="CategoryName": 에디터의 변수 그룹화를 위해 카테고리를 설정.
메모리 관리 및 성능
- Transient: 런타임에서만 존재하며 저장되지 않음.
- SaveGame: 이 변수는 저장될 수 있음.
- Replicated: 네트워크로 복제됨 (멀티플레이 환경에서 사용).
메타 옵션 지정자
- meta=(ClampMin="0.0"): 에디터에서 변수 입력 시 최소값을 제한.
- meta=(AllowPrivateAccess="true"): 해당 멤버가 private로 선언되어 있어도, 에디터나 블루프린트에서 접근할 수 있도록 허용.
UFUNCTION() 매크로
Blueprint 관련 지정자
- BlueprintCallable: Blueprint 이벤트 그래프(노드)에서 호출 가능한 함수로 만듦.
- BlueprintPure: Getter 역할만 수행 (Exec 핀 없이 Return Value만 노출).
- BlueprintImplementableEvent:
- 함수의 선언만 C++에 있고, 구현은 블루프린트에서 함. C++ 코드에서는 함수 이름만 정의하고, 실제 동작은 Blueprint Event Graph 안에서 이벤트 노드처럼 구현됨.
- C++에서 호출도 가능함.
지정자를 하나도 쓰지 않으면?
UPROPERTY()와 마찬가지로, 함수가 언리얼 리플렉션에 등록되지만, Blueprint에 특별히 노출되지 않음.
엔진이 함수의 존재는 파악하되, Blueprint에서 직접 호출할 수 없게 숨겨둔 상태라고 보면 됨.
리플렉션 시스템 이해하기
블루프린트를 사용하면 스테틱 메쉬 컴포넌트를 쉽게 추가하고 메쉬 모양도 클릭하여 설정할 수 있다. 반면에, C++로 액터를 구현할 때는 일일이 다 구현해야 해서 불편하다. 하지만 C++에서 리플렉션 시스템을 이용하면 메쉬 설정과 머터리얼 설정 등을 쉽게 처리할 수 있어서 작업이 훨씬 편리해진다.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Item.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogTeam, Warning, All); // (카테고리 이름, 로그 심각도 설정, 활성화)
UCLASS()
class START_API AItem : public AActor
{
GENERATED_BODY()
public:
AItem();
1) C++ 클래스 리플렉션에 등록하기
- #include "Item.generated.h":
- 언리얼 엔진이 자동 생성하는 헤더 파일.
- 리플렉션 및 엔진 통합에 필요한 코드 포함.
- 반드시 헤더 파일의 마지막 #include 구문 아래에 위치!
- UCLASS():
- 클래스를 리플렉션 시스템에 등록.
- 블루프린트 등 에디터에서 클래스 인식 및 사용 가능.
- GENERATED_BODY():
- 코드 생성 도구가 사용하는 코드 삽입.
- 클래스 내부 리플렉션 정보 자동 생성.
2) C++로 만든 아이템 클래스
- 기본 부모 클래스는 Item이 된다.
- 블루프린트 클래스로 생성하면, C++로 작성된 속성이나 함수를 '시각적'으로 다룰 수 있게 된다.
3) 변수에 리플렉션 시스템 적용하기
protected:
FVector Location;
FRotator Rotation;
FVector Scale;
float SpeedZ = 200.0f; // Z축 상하 이동 속도
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Item|Property")
float RotationSpeed = 90.0f; // 회전 속도
float ScaleFreq = 2.0f; // 스케일 변경 2초 주기
float TimeElapsed = 0.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Components") // 상위 카테고리 Item, 하위 Components
USceneComponent* SceneRoot;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Components");
UStaticMeshComponent* StaticMesh;
UAudioComponent* AudioComponent;
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
헤더 파일에서 리플렉션 시스템을 이용해, 에디터에서 수정할 수 있도록 EditAnywhere로 설정했으니 해당 부분을 지워도 된다.
: 왜? ➡️ 리플렉션 시스템 등록했으니, 에디터에서 수정할 수 있게 됐으니까!
📽️ 영상
4) UFUNCTION() : 함수에 리플렉션 시스템 적용하기
복잡한 C++ 로직을 블루프린트에서 간단한 노드로 불러와 제어할 수 있어서 작업 효율이 높아짐.
- UPROPERTY()가 멤버 변수를 리플렉션 시스템에 등록한다면,
- UFUNCTION()은 멤버 함수를 등록함!
.h
UFUNCTION(BlueprintCallable, Category = "Item|Action")
void ResetActorPosition();
UFUNCTION(BlueprintPure, Category = "Item|Property")
float GetSpeed() const;
UFUNCTION(BlueprintImplementableEvent, Category = "Item|Event")
void PickedUP();
.cpp
void AItem::BeginPlay()
{
Super::BeginPlay();
PickedUP();
// 초기 위치, 회전, 스케일 값 저장.
Location = GetActorLocation();
Rotation = GetActorRotation();
Scale = GetActorScale();
}
// ~ 중략 ~
void AItem::ResetActorPosition()
{
SetActorLocation(FVector::ZeroVector);
}
float AItem::GetRotationSpeed() const
{
return RotationSpeed;
}
`FVector::ZeroVector` : 원점으로.
➡️ 블루프린트에서 아래와 같이 함수를 찾을 수 있다.