Hey everyone i just wanted to post this quik tutorial about creating widgets in C++.
For a tutorial on How to extend a UUserWidget:: for UMG in C++ see link.
Now doing this is prety straight forward except for when dealing with multiplayer.
And i spent some houers trying diferent solution and this is what i came up with.
1 In your player controller class add two new member variabels like this.
// The class that will be used for the players Inventory UI
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
TSubclassOf<class UInventoryUserWidget> InventoryUIClass;
// The instance of the players Inventory UI Widget
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
class UInventoryUserWidget* InventoryWidget;
2 Override the BeginPlay() method in your Player Controller class.
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
// Only create the UI on the local machine (dose not excist on the server.)
if (IsLocalPlayerController())
{
if (InventoryUIClass) // Check the selected UI class is not NULL
{
if (!InventoryWidget) // If the widget is not created and == NULL
{
InventoryWidget = CreateWidget<UInventoryUserWidget>(this, InventoryUIClass); // Create Widget
if (!InventoryWidget )
return;
InventoryWidget->AddToViewport(); // Add it to the viewport so the Construct() method in the UUserWidget:: is run.
InventoryWidget->SetVisibility(ESlateVisibility::Hidden); // Set it to hidden so its not open on spawn.
}
}
}
}
3 Open and close inventory UI example.
void AMyPlayerController::ToggleInventory()
{
if (bShowingInvetory)
bShowingInvetory = false;
else
bShowingInvetory = true;
if (InventoryWidget)
{
if (bShowingInvetory)
{
InventoryWidget->SetVisibility(ESlateVisibility::Visible);
}
else {
InventoryWidget->SetVisibility(ESlateVisibility::Hidden);
}
}
}
Thats it!
Now if you are wondering way I don`t create it on the server, how do you have server > client behavior?
I do this by creating delegates on the Player Controller and bind them in the Contruct_Implementation() method, that in turns call a âBlueprintImplementableEventâ to notifie the widget it self so it can behave accordingly.
Note: OnPlayerPickupItem delegate is called from server to client using a Remote Procedure Call (RPC)
is a example of this.
void UInventoryUserWidget::Construct_Implementation()
{
Super::Construct_Implementation();
AMyPlayerController* PC = CAST_TO_MY_PC(GetOwningPlayer());
if (PC)
{
// Calls CallPlayerPickupItem() that in turn calls the "BlueprintImplementableEvent" on OnPlayerPickedItem()
PC->OnPlayerPickupItem.RemoveDynamic(this, &UInventoryUserWidget::CallPlayerPickupItem); // Remove the delegate before binding it. (Its always safe to unbind a delegate.)
PC->OnPlayerPickupItem.AddDynamic(this, &UInventoryUserWidget::CallPlayerPickupItem); // Bind the delegate from the PC that calls the BlueprintImplementableEvent.
}
}
Hope this was helpful i spent some time on the crash i got when not checking for IsLocalPlayerController().
And tought it might be a nice share for anyone else having the issue.