How do I reference a created widget from PlayerController Class?

I have created a widget inside of my PlayerController C++ Class, and I need a way to reference that widget and it’s functions from inside of my PickupItem.cpp.

PlayerController.h:


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widgets")
	TSubclassOf<class UUserWidget> winventorywidget;

PlayerController.cpp:


void AThePlayerController::BeginPlay()
{
	Super::BeginPlay();

	if (winventorywidget) // Check if the Asset is assigned in the blueprint.
	{
		// Create the widget and store it.
		UInventoryHUD* InventoryWidget = Cast<UInventoryHUD>(CreateWidget<UUserWidget>(this, winventorywidget));

		if (InventoryWidget)
		{
			//let add it to the view port
			InventoryWidget->AddToViewport();
		}

		InventoryWidget->addSlotEvent("Hello"); //special event inside of my UInventoryHUD
		bShowMouseCursor = true;
	}

}

Basically, the InventoryWidget is a UInventoryHUD object which extends UUserWidget. All UInventoryHUD objects contain an event called “addSlotEvent()” which set the text of a textblock to whatever is in the arguments. Now, I need a way to call InventoryWidget->addSlotEvent(“Hello”) from inside of my Pickup.cpp’s OverLapEvent method (basically when a player overlaps the item, the item is picked up, and it’s name is suppose to be displayed in the inventory slot).

I need to know how I can reference the functions/events inside of InventoryWidget from my Pickup.cpp class. Keep in mind that when the Widget has already been created when the playercontroller is launched, so I can’t really create it again everytime a player picks up an item.

Seems the easiest way would be to call UGameplayStatics::GetPlayerController() from your Pickup class, something like:



AThePlayerController* controller = Cast<AThePlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
if(controller)
{
   controller->InventoryWidget->addSlotEvent("Yo");
}

Thanks alot! You don’t know how long I have been trying to figure this out.

Avoid using UGameplayStatics::GetPlayerController, especially if you ever plan on doing multiplayer. It’s horribly risky to assume that your player is always at index 0 and will lead to huge headaches down the road.

For instance, what if a non-character overlaps the pickup? Do you verify what is overlapping an item before firing pick up logic? If not, any overlap would end up calling your event on player controller 0.

If you do verify what is overlapping, then that incidentally is also your entry point. Consider:



void APickup::OnPickupOverlap( AActor* OtherActor )
{
	AMyPlayerCharacter* PC = Cast<AMyPlayerCharacter>( OtherActor );
	if( PC != nullptr )
	{
		AThePlayerController* PCController = Cast<AThePlayerController>( PC->Controller );
		if( PCController != nullptr )
		{
			PCController->InventoryWidget->addSlotEvent( PickupName );
		}
	}
}


Much cleaner and follows naturally.

I agree this is a much cleaner approach.

For a single player game I don’t see any risk in using UGameplayStatics::GetPlayerController. Maybe I’m missing something?

It’s safe, yes. But I’ve had the misfortune of working on introducing multiplayer a project that assumed a single player and used direct, singleton-like accesses to player 0.

So I’m thinking that if there are ways to access the information you need in a multiplayer compatible way, it’s not a bad habit to stick to those. :slight_smile:

:eek: ahhh, that sounds brutal. Great advice to live by :D, I’m going to adopt it myself.