Trying WCode's UMG Widget c++ and... TSubclassOf Causing trouble...

Just like one of replies, it happened to me that TSubclassOf<class UInventoryUserWidget> InventoryUIClass not being initialized (still NULL)…

I did googling or being experiemental… I have been grasping hard time about what is TSubclassOf<> exactly…

and how do I manually initialize TSubclassOf<> by C++?

I tried NewObject<>() also (which seems lacking idea), but cannot put into right thought.

I really need to use TSubeclassOf<> if I have to use custom Widget in C++…

Help me please.

You can set a reference to the blueprint class in your player controller blueprint or to do it in c++ do


 
FStringClassReference MyWidgetClassRef(TEXT("/Game/Widgets/InventoryUserWidget_C"));
 InventoryUIClass = MyWidgetClassRef.TryLoadClass<UInventoryUserWidget>();


Where the path is the reference path to the blueprint widget in your project. Your blueprint widget should inherit from your custom c++ widget.

thanks i gonna try it right now. :slight_smile:


 
FStringClassReference MyWidgetClassRef(TEXT("/Game/Widgets/InventoryUserWidget_C"));
 InventoryUIClass = MyWidgetClassRef.TryLoadClass<UInventoryUserWidget>();


inside TEXT, I tried widget’s blueprint reference and original C++ reference… Original C++ reference works (which means not NULL), but it does not show anything in the screen… even i checked whether the program initiated adding the widget to viewport… which seems it did(?)… but still nothing. hmm… What could have I done wrong…

TSubclassOf is a variable that you’re supposed to set in a Blueprinted version of that class, usually. If you do this for example:



UPROPERTY(EditDefaultsOnly, Category = "My Settings")
TSubclassOf<class UMyWidget> WidgetClass;


Then create a Blueprint version of that class, you will see this as an exposed variable. You should really avoid using string references to classes and assets where possible.

Also, to avoid loading lots of classes when you don’t neccesarily need to, there’s also a TAssetSubclassOf<>, which doesn’t load the object in question until you call LoadSyncronous() on it.

Thank you for reply. I gonna try out with TAssetSubclassOf<>;

Here’s an example of me using it in Code.



	UPROPERTY(EditDefaultsOnly, Category = "Game Widgets")
	TAssetSubclassOf<USCGame_MissionItem> MissionItemWidget;

	// Create a new mission widget, add to the viewport and the active widgets array
	USCGame_MissionItem* NewItemWgt = CreateWidget<USCGame_MissionItem>(GetOwningPlayerController(), MissionItemWidget.LoadSynchronous());


1 Like

OMG, thank you for posting code. I was thinking how am I suppose to do it all over in current code… Q.Q

I tried similar way as your code…

but I get an error message during runtime and also it does not show my widget…

that message is … “CreateWidget can only be used on UUSerWidget children”

I am clueless again…

here is my code though



UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
		TAssetSubclassOf < class UActionsPanelWidget > GoodsInventoryInBattleUIClass;
	//The instance of the players Inventory UI Widget
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Player, HUD and UI")
	class UActionsPanelWidget* GoodsInventoryInBattleWidget;

if (IsLocalPlayerController())
{
                         if (!GoodsInventoryInBattleWidget) // If the widget is not created and == NULL
			{
                                GoodsInventoryInBattleWidget = CreateWidget<UActionsPanelWidget>(this, GoodsInventoryInBattleUIClass.LoadSynchronous());
				if (!GoodsInventoryInBattleWidget)
					return;
				GoodsInventoryInBattleWidget->AddToViewport();// Add it to the viewport so the Construct() method in the UUserWidget:: is run.
				GoodsInventoryInBattleWidget->SetVisibility(ESlateVisibility::Hidden);// Set it to hidden so its not open on spawn
			}
}




and… tried GetOwningPlayerController(), but does not work in my controller class. I have to use “this” instead

Yeah that’s fine, I’m creating my widgets in the HUD class because I use it as a widget manager, so I have to use that instead.

CreateWidget is a static function, you can call it from anywhere it just needs either an Owning Game Instance, Player Controller or World I believe.

still though… weird error message “CreateWidget can only be used on UUSerWidget children” with not showing mywidget… what did i mess up this time… hmm…

Yeah so that means you haven’t set the variable to anything.

You need to create a Blueprint version of your player controller and set that variable to something, i.e. a UMG widget you’ve created. At the moment it’s empty.

Yeah so that means you haven’t set the variable to anything.

You need to create a Blueprint version of your player controller and set that variable to something, i.e. a UMG widget you’ve created. At the moment it’s empty.
[/QUOTE]

Alright. Setting BP version of that my controller class in Game Mode solves everything! Thank you so much . It was nightmare for me in few days and you helped me :slight_smile:

After making few widgets… I think I should make manager for widgets.

Just use the HUD class as the manager. It’s a good central place to access all your widgets from and really that’s its purpose now that Canvas isn’t really used anymore.

It’s also relatively easy to access the HUD instance from anywhere in game code, since you only need to get the player controller to access it.

wow Quick Reply… Thank you very much. I thought about making a UObject in Game Instance… but HUD class sounds nicer

Thinking how should I name it and design classes… so many widgets with different functions…

a bit silly question… there is so many Widgets - A B C D E F… e.t.c. but sometimes they have same function or not. hmm…My question is… is it good idea to inherit from base UserWidget class and keep them in Array or TMap?

Nevermind, I can come up with my own… sorry to bother again