2024.08.31
이번 글에서는 PickUpDefense 게임에서 마우스 입력을 처리하고, 위젯을 동적으로 생성하는 과정에서 발생한 문제들을 해결하는 방법에 대해 다룹니다. 특히, 언리얼 엔진에서 액터 클릭 이벤트와 UI 위젯 생성 시 발생하는 충돌을 해결하는 데 중점을 두었습니다.
게임 내에서 액터를 클릭했을 때 특정 동작을 수행하도록 하려 했으나, 처음에는 클릭 이벤트가 트리거되지 않는 문제가 발생했습니다. 특히, OnClicked
이벤트가 호출되지 않았으며, 이는 충돌 설정이나 입력 처리 방식에 문제가 있을 수 있었습니다.
BaseMesh
의 충돌 설정을 다시 확인하고, OnClicked
이벤트를 PlayerController와 연동하여 클릭 이벤트를 처리하도록 수정했습니다.BaseMesh->SetCollisionProfileName(TEXT("BlockAll"));
BaseMesh->SetGenerateOverlapEvents(true);
BaseMesh->SetNotifyRigidBodyCollision(true);
BaseMesh->OnClicked.AddDynamic(this, &ABaseVehicle::OnMeshClicked);
이렇게 수정한 후, 액터 클릭 이벤트가 정상적으로 트리거되었고, UE_LOG
를 통해 디버깅 메시지를 출력할 수 있었습니다.
액터를 클릭했을 때, 해당 위치에 옵션 메뉴 위젯을 생성하려 했습니다. 하지만 CreateWidget
함수 호출 시 ABaseCharacter
를 소유자로 사용하려 했던 것이 문제를 일으켰습니다. CreateWidget
함수는 UWorld
, APlayerController
, 또는 UGameInstance
타입의 소유자만을 지원합니다.
CreateWidget
의 소유자로 사용하려 했기 때문에 발생한 컴파일 오류였습니다.APlayerController
를 소유자로 지정하여 위젯을 생성하도록 수정했습니다.UOptionMenu* OptionMenuWidget = CreateWidget<UOptionMenu>(PlayerController, UOptionMenu::StaticClass());
이제 위젯이 정상적으로 생성되었고, 마우스 클릭 위치를 기준으로 살짝 오른쪽 아래에 나타나도록 설정할 수 있었습니다.
생성된 옵션 메뉴에서 버튼을 클릭했을 때 특정 동작을 수행하도록 구현했습니다. 이를 위해 버튼 클릭 이벤트에 동작을 바인딩하여 처리했습니다.
AddButton
함수 내에서 버튼 생성 시, 클릭 이벤트를 특정 함수에 바인딩했습니다.if (ButtonName == FName("삭제하기"))
{
Button->OnClicked.AddDynamic(this, &UOptionMenu::OnDeleteButtonClicked);
}
void UOptionMenu::OnDeleteButtonClicked()
{
UE_LOG(LogTemp, Warning, TEXT("삭제하기 버튼이 클릭되었습니다!"));
RemoveFromParent(); // 이 위젯을 화면에서 제거
}
위젯을 동적으로 생성하고, UI에 필요한 정보를 할당하는 방법에 대해 학습했습니다.
위젯을 동적으로 생성한 후, 해당 위젯에 필요한 데이터를 설정합니다. 아래는 UShopPanelSlot
위젯을 동적으로 생성하고, 카드 정보를 할당하는 과정입니다.
UShopPanelSlot* PanelSlot = WidgetTree->ConstructWidget<UShopPanelSlot>(UShopPanelSlot::StaticClass(), BorderName);
if (PanelSlot)
{
// 변수에 값을 설정
PanelSlot->CardName = TEXT("모르가나");
PanelSlot->Synergy1Text = TEXT("마녀");
PanelSlot->Synergy2Text = TEXT("박쥐여왕");
PanelSlot->Synergy3Text = TEXT("보호술사");
PanelSlot->PriceText = TEXT("$5");
// UpdateCardInfo를 호출하여 UI를 업데이트
PanelSlot->UpdateCardInfo(); // 즉시 UI를 갱신
}
위젯 생성 후 데이터를 할당할 때, 일부 위젯 컴포넌트가 null
인 상태에서 접근하려고 하여 게임이 크래시되는 문제가 발생했습니다. 이는 위젯이 아직 완전히 초기화되지 않았기 때문이었습니다. 이를 해결하기 위해, 다음과 같은 조치를 취했습니다.
null
체크 추가: 각 컴포넌트가 null
이 아닌지 확인한 후 데이터를 설정하도록 코드를 수정했습니다.void UShopPanelSlot::UpdateCardInfo()
{
if (ensure(Synergy1))
{
Synergy1->SetText(FText::FromString(Synergy1Text));
}
if (ensure(Synergy2))
{
Synergy2->SetText(FText::FromString(Synergy2Text));
}
if (ensure(Synergy3))
{
Synergy3->SetText(FText::FromString(Synergy3Text));
}
if (ensure(Name))
{
Name->SetText(FText::FromString(CardName));
}
if (ensure(Price))
{
Price->SetText(FText::FromString(PriceText));
}
if (ensure(Image) && !ImageDir.IsEmpty())
{
UTexture2D* Texture = Cast<UTexture2D>(StaticLoadObject(UTexture2D::StaticClass(), nullptr, *ImageDir));
if (ensure(Texture))
{
Image->SetBrushFromTexture(Texture);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Failed to load texture from path: %s"), *ImageDir);
}
}
}
이 수정으로 인해 더 이상 null
참조로 인한 크래시가 발생하지 않았고, 위젯이 정상적으로 동작했습니다.
NativeOnDragCancelled
함수에서 드래그가 취소되었을 때 메쉬를 로드하고 적용하는 방법도 다루었습니다. 이 과정에서 런타임 중에 메쉬를 안전하게 로드하는 방법에 대해 논의했습니다.
void UShopPanelSlot::NativeOnDragCancelled(const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)
{
// 메쉬 로드 시 반드시 성공하도록 확인
UStaticMesh* LoadedMesh = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), nullptr, TEXT("/Game/Meshes/MyMesh.MyMesh")));
ensureMsgf(LoadedMesh, TEXT("Failed to load mesh at path: /Game/Meshes/MyMesh.MyMesh"));
// MyMeshComponent가 유효한지 확인한 후 메쉬 할당
ensureAlwaysMsgf(MyMeshComponent && LoadedMesh, TEXT("Mesh Component is null or Mesh failed to load. Cannot assign mesh."));
if (ensure(MyMeshComponent) && ensure(LoadedMesh))
{
MyMeshComponent->SetStaticMesh(LoadedMesh);
}
// MyMeshComponent가 유효하지 않을 경우에 대비한 추가 검증
if (!ensureMsgf(MyMeshComponent, TEXT("MyMeshComponent is null in NativeOnDragCancelled")))
{
UE_LOG(LogTemp, Error, TEXT("Cannot set mesh because MyMeshComponent is null"));
}
}
이 코드에서는 StaticLoadObject
를 사용하여 런타임 중 메쉬를 로드하고, 해당 메쉬를 컴포넌트에 할당했습니다.
이번 작업을 통해 PickUpDefense의 UI 시스템에서 발생한 몇 가지 주요 문제를 해결할 수 있었습니다. 특히, 마우스 입력 처리와 위젯 동적 생성 과정에서 발생한 문제를 효과적으로 해결했습니다.
CreateWidget
함수의 올바른 사용법을 이해하고, 이를 통해 UI를 동적으로 생성하는 방법을 확립했습니다.이번 글에서는 언리얼 엔진 5 위젯에서 마우스 입력을 처리하고 위젯을 동적으로 생성하는 방법에 대해 다루었습니다. 위젯 생성 과정에서 발생한 문제들과 그 해결 방법을 통해 UI 시스템을 안정적으로 구현하는 방법을 배울 수 있었습니다.
이 글이 PickUpDefense 게임의 개발 과정을 이해하는 데 도움이 되길 바라며, 다음 글에서는 더욱 흥미로운 주제로 찾아뵙겠습니다. 감사합니다!