"_C"가 붙는지 안 붙는지 차이?
클래스(Class) 참조 or 애셋(Asset) 참조
WBP_TitleLevel : 블루프린트 애셋 자체
→ 그냥 "위젯 블루프린트 파일"
WBP_TitleLevel_C : 그 블루프린트 애셋이 컴파일된 클래스
→ "그 블루프린트로 생성할 수 있는 C++ 클래스" (붕어빵 틀)
FClassFinder 같은 경우는 UClass*를 찾는 거니까 "_C" 클래스 경로를 지정해야 함
그래야 코드에서 CreateWidget 같은 함수로 인스턴스를 생성할 수 있음
레벨은 클래스가 아니라 맵 애셋임 (붕어빵 반죽)
ServerTravel, OpenLevel 같은 함수는 UClass*를 요구하는 게 아니라 단순히 레벨 이름/경로만 필요함
그래서 뒤에 _C 붙일 필요 없이 /Game/.../LV_Waiting 이라고만 쓰면 됨
// WaitingLevel.umap (콘텐츠 브라우저 경로: /Game/Maps/WaitingLevel)
UGameplayStatics::OpenLevel(this, FName("/Game/Maps/WaitingLevel"));
// MyActorBP 라는 블루프린트 액터가 있다고 가정
static ConstructorHelpers::FClassFinder<AActor> BPActorClass(TEXT("/Game/Blueprints/BP_MyActor.BP_MyActor_C"));
if (BPActorClass.Succeeded())
{
// _C 클래스 참조를 통해서 스폰 가능
GetWorld()->SpawnActor<AActor>(BPActorClass.Class, FVector::ZeroVector, FRotator::ZeroRotator);
}
BP_MyActor_C 라고 적어야 UClass*를 얻을 수 있음
_C 붙이면: 블루프린트 클래스 → C++에서 Spawn, CreateWidget 가능
_C 안 붙이면: 단순 애셋 → 레벨, 사운드, 머티리얼 같은 리소스 불러올 때
UPROPERTY(meta=(BindWidget), BlueprintReadOnly)
UPROPERTY(meta=(BindWidget), BlueprintReadOnly)
UButton* StartButton;
BindWidget
→ UMG 블루프린트(WBP_TitleLevel)에 있는 위젯과 자동으로 연결해 줌. 이름이 정확히 일치해야 함.
BlueprintReadOnly
→ 블루프린트에서 읽을 수는 있지만, 값 변경은 불가.
(예: Graph에서 읽기 노드만 생성 가능)
접근 제어는 C++ 클래스의 public/protected/private 위치에 따라 달라짐.
UPROPERTY(meta=(BindWidget), BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
UPROPERTY(meta=(BindWidget), BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
UButton* QuitButton;
여기서 AllowPrivateAccess="true"는 블루프린트에서 private 멤버라도 접근할 수 있게 허용한다는 의미
C++에서는 private: 영역에 선언했더라도 BP에서 Get 노드로 접근 가능해짐
언리얼 C++ 에서 private 멤버를 BindWidget 할 때 이 태그를 붙이는 경우가 많른
위젯 변수는 BP에서 읽기만 하면 되고, 코드에서는 캡슐화를 유지하고 싶기 때문임
둘 다 BindWidget + ReadOnly라서 동작은 거의 같음
차이점은 C++ 접근 제어자가 private:일 때
💡 보통 UMG 바인딩용 위젯 변수는 private:에 두고
UPROPERTY(meta=(BindWidget), BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
이렇게 써서 캡슐화 유지 + BP 접근 허용을 동시에 처리하는 게 좋음