간단한 디자인 영역이라 더 이쁘게 만들어도 될꺼같은데 전 간단하게 만들겠습니다
NPC를 누를시 해당 위젯을 띄우기 위해 NPC 클래스에 위젯 클래스를 선언하고 해당 위젯을 띄우기 위해 Interaction 함수에 반응시 해당 위젯을 나타내는 로직을 작성
NPC.h
protected:
UPROPERTY()
class UUserWidget* itemShopWidget;
NPC.cpp
void ANPC::Interaction()
{
//UE_LOG(LogTemp, Log, TEXT("Interacted with object"));
// 상호 작용 로직
APlayerController* myPlayerController = UGameplayStatics::GetPlayerController(this, 0);
myPlayerController->SetViewTargetWithBlend(this, 1.0f);
myPlayerController->SetInputMode(FInputModeUIOnly());
myPlayerController->SetShowMouseCursor(true);
HideInteractionWidget();
if (ItemShopWidgetClass)
{
itemShopWidget = CreateWidget<UUserWidget>(GetWorld(), ItemShopWidgetClass);
if (itemShopWidget)
itemShopWidget->AddToViewport();
}
}
해당 위젯이 뜨면 다음엔 Exit 버튼을 누를시 다시 컨트롤러를 Player로 바꾸겠습니다
위젯의 기능이나 또는 그런 부분은 블루 프린트로 간단하게 표현할 예정이다
해당 본격 상점 인벤토리를 만들기 위해 위젯을 하나 더 만든다
Data Table도 하나 만든다
Test용으로 쓰기 위해 마켓 플레이스 가서 해당 아이콘 에셋을 다운 받는다
가상 예제로 DataTable
만들기
NPC.cpp
void ANPC::Interaction()
{
//UE_LOG(LogTemp, Log, TEXT("Interacted with object"));
// 상호 작용 로직
APlayerController* myPlayerController = UGameplayStatics::GetPlayerController(this, 0);
myPlayerController->SetViewTargetWithBlend(this, 1.0f);
myPlayerController->SetInputMode(FInputModeUIOnly());
myPlayerController->SetShowMouseCursor(true);
HideInteractionWidget();
if (ItemShopWidgetClass)
{
itemShopWidget = CreateWidget<UUserWidget>(GetWorld(), ItemShopWidgetClass);
if (itemShopWidget)
itemShopWidget->AddToViewport();
FName Property(TEXT("OwnerNPC"));
FProperty* _NPCPropert = itemShopWidget->GetClass()->FindPropertyByName(TEXT("OwnerNPC"));
if (_NPCPropert)
{
FObjectProperty* ObjectProperty = CastField<FObjectProperty>(_NPCPropert);
if (ObjectProperty && ObjectProperty->PropertyClass == ANPC::StaticClass())
{
ObjectProperty->SetObjectPropertyValue_InContainer(itemShopWidget, this);
}
}
}
}
FName Property(TEXT("OwnerNPC")); FProperty* _NPCPropert = itemShopWidget->GetClass()->FindPropertyByName(TEXT("OwnerNPC"));
- 블루프린트 변수 'OwnerNPC'에 접근
- 'Expose on Spawn'가 활성화된 NPC 변수를 설정
- 블루프린트 위젯에 'OwnerNPC'라는 이름으로 설정된 변수 ( Expose on Spanw 옵션이 활성화 된 변수 )를 찾습니다.
if (_NPCPropert)
- _NPCProperty가 유효한지 확인
- 위의 FindPropertyByName 함수가 정상적으로 'OwnerNPC' 변수를 확인합니다
- 만약 'OwnerNPC'라는 변수를 블루프린트 위젯에서 찾지 못했다면 _NPCProperty는 nullptr이 됩니다.
FObjectProperty* ObjectProperty = CastField<FObjectProperty>(_NPCPropert);
- 찾은 _NPCPropert변수를 FObjectProperty로 캐스팅
- _NPCPropert가 객체 타입의 변수의 경우에만 FObjectProperty로 캐스팅 할 수 있습니다
- 여기서 'OwnerNPC'가 ANPC 타입의 객체 변수이므로 FObjectProperty로 캐스팅 시도 합니다
if (ObjectProperty && ObjectProperty->PropertyClass == ANPC::StaticClass())
- FObjectProperty가 유효한지 확인하고, 이 변수가 ANPC 클래스와 일치한지 확인
- FObjectProperty가 유요하고, 그 변수가 정확히 ANPC 클래스의 객체인 경우에만 아래 코드를 실행합니다
ObjectProperty->SetObjectPropertyValue_InContainer(itemShopWidget, this);
- 찾은 FObjectProperty 변수에 현재 NPC 객체( this )를 할당
- SetObjectPropertyValue_InContainer 함수는 주어진 객체 ( itemShopWidget ) 의 특정 객체 변수 ( ObjectProperty )에 값을 설정해줍니다
- 여기서는 itemShopWidget 위젯의 OwnerNPC 변수에 현재 NPC 객체 ( this )를 설정하는 역할을 합니다
생성과 동시에 할당된 변수를 사용해서, ‘OwnerNPC’ 의 Null Error 가 발생
해결해보자
NPC.cpp
void ANPC::Interaction()
{
//UE_LOG(LogTemp, Log, TEXT("Interacted with object"));
// 상호 작용 로직
APlayerController* myPlayerController = UGameplayStatics::GetPlayerController(this, 0);
myPlayerController->SetViewTargetWithBlend(this, 1.0f);
myPlayerController->SetInputMode(FInputModeUIOnly());
myPlayerController->SetShowMouseCursor(true);
HideInteractionWidget();
if (ItemShopWidgetClass)
{
itemShopWidget = CreateWidget<UUserWidget>(GetWorld(), ItemShopWidgetClass);
// 블루프린트 변수 'OwnerNPC'에 접근
FName Property(TEXT("OwnerNPC"));
FProperty* _NPCPropert = itemShopWidget->GetClass()->FindPropertyByName(TEXT("OwnerNPC"));
if (_NPCPropert)
{
FObjectProperty* ObjectProperty = CastField<FObjectProperty>(_NPCPropert);
if (ObjectProperty && ObjectProperty->PropertyClass == ANPC::StaticClass())
{
ObjectProperty->SetObjectPropertyValue_InContainer(itemShopWidget, this);
}
}
if (itemShopWidget)
itemShopWidget->AddToViewport();
// 위치를 바꾸주면 해결된다
}
}