I have found a solution!
First, the problem was that I was trying to add the widget to the viewport inside itself, and you dont have a BeginPlay
function in widget blueprints, BUT you can call ANY other widget inside a widget excluding itself in the NativeConstruct
(so you can add widget to the viewport if it is not itself). Now I have added the Inventory through the character c++ class with the following commands:
Header
- First
#include
the proper widget header file to your c++ character/gamemode/playerController header (for me it is CPP_Inventory.h
): #include "CPP_Inventory.h"
- Then declare some variables
UPROPERTY(EditAnywhere)
TSubclassOf<UCPP_Inventory> InventoryClass;
UPROPERTY(VisibleInstanceOnly, Category="Runtime")
UCPP_Inventory* Inventory;
CPP
- Under
BeginPlay
create the widget and add it to the viewport
Inventory = CreateWidget<UCPP_Inventory>(GetWorld(),InventoryClass);
Inventory->AddToViewport();
Now the coding part is done, but it will crash the editor if you try to play, that is because we havent set the proper class for the created variable above (TSubclassOf<UCPP_Inventory> InventoryClass;
). For that we just have to set the class here:

This is under Graph->Class Defaults, and your variable name.
You can add some further code if you dont want to crash the editor if you forgot to select the class here, to do that just add something similar to this:
if(IsValid(InventoryBarSlotClass)){
InventoryBarSlot = CreateWidget<UCPP_InventoryBarSlot>(GetWorld(),InventoryBarSlotClass);
if(InventoryBarSlot != nullptr){
InventoryBarSlot->AddToViewport();
}
}
The above code doesnt try to create the widget if the class is not set, so the editor wont crash.
Now back to the original problem, I wanted to add the created widget to the uniform grid panel 10 times.
- Include necessary header files
- Create variables and two functions inside header:
protected:
void AddInventoryBarSlots();
void NativeConstruct() override;
UPROPERTY( meta = (BindWidget))
UImage* InventoryBarFrame;
UPROPERTY( meta = (BindWidget))
UUniformGridPanel* InventoryBarSlotPanel;
UPROPERTY(EditAnywhere)
TSubclassOf<UCPP_InventoryBarSlot> InventoryBarSlotClass;
- Code the created
AddInventoryBarSlots
function
function void UCPP_Inventory::AddInventoryBarSlots(){
for(int i = 0; i <= 9; i++)
{
UPROPERTY(VisibleInstanceOnly, Category="Runtime")
UCPP_InventoryBarSlot* InventoryBarSlot = CreateWidget<UCPP_InventoryBarSlot>(GetWorld(),InventoryBarSlotClass);
InventoryBarSlotPanel->AddChildToUniformGrid(InventoryBarSlot,0,i);
}
}
- Then call it inside the
NativeConstruct
function
void UCPP_Inventory::NativeConstruct(){
Super::NativeConstruct();
AddInventoryBarSlots();
}
- Lastly set the class inside the Blueprint like before:
Result:
All this sounds/looks way more complicated then it really is!