Is there a way to create UI components?

Probably the best analogy to describe what I mean is Material instances. So, after I created a material I can right click on it and create its instance, where I can change any values and textures.

I’m looking for something similar, for a method where I could create a Master widget with it’s own behaviour, like animations, and create instances of it which I could fill with different data from different sources.

As an example, I’m working on UI of 2 similar screens for my game, on one of them I choose a level to play and a vehicle on another. The idea is to reuse the same UI component (card).


I created the Level card the way that on a Pre-construct event it’s variables are populated with data from data table, then, it’s children are added in a scroll box and their amount depends on the amount of rows in that data table.

I want to do the same with the vehicle cards as well, which will pull data from another source, this time it’s data asset with different data structure (forgot to mention that the image on the card is not the only data I fill it with, it has a lot more which renders outside the card in its parent widget, like Level name, time records, level to open etc., and for vehicles there should be stats like speed, handling…):

The simple way is to duplicate the level card and rewrite its pre-construct logic, but that doesn’t seem scalable at all, for instance, in the future I would like to change the card layout or its animations and I have to do it twice or even more times for each card :confused:

I hope I described it well and will be grateful for any suggestions. Thank you!

Widget inheritance does not work the same as actors’. You get variables and functions but the hierarchy is lost as soon as you add any element, re-parenting can be done like so:

image


A neat way of working with widgets and making systems modular is via Named Slots.

You make a user widget, give it a pretty configurable border, script mouse enter / leave, highlights, animations and whatnots, but you leave the content out of it. Instead, add a Named Slot:

image

This slot is exposed and you can drop whatever you want inside:

image

The fancy border can query the Named Slot to fetch the content user widget:

image

And act accordingly if needed.

If the Named Slot contains ContentWidgetA → change the border layout, if ContentWidgetB is found, use another anim. This can be done via casting to check what’s inside the slot, or an interface that returns content data or the border can be given an enumerator if you want to control it manually.


You end up with 2 user widgets. The Fancy Border and many user widgets that can be dropped inside. This, at least, allows you to separate the container from the content.

1 Like

That sounds promising! I did not work with Named Slots yet, I’m going to dig into it and try this approach. Thank you!

1 Like

To add to this, let’s say the fancy border has some variables and a custom event:

If you now create a brand new user widget and re-parent it:

You get access to those vars, the custom event would print hello :point_up: and the widget has all the borders…

image

…even though they may not show up in the hierarchy. This is pretty much all the widgets have to offer in UMG when it comes to inheritance / modularity. And this User Widget Child still has a named slot that can be populated. So yes, you can have instances that extend the behaviour of the parent providing you do not mess with the hierarchy too much. Ideally, not at all.

1 Like

So, I’ve watched some youtube videos and re-read this a few times. For the last few hours I was trying to make it work and feel that I’m close, but still I have not enough understanding of how to work with Named Slots. It looks simple but…

What I’ve done:

  1. Split initial card widget into two parts, one is border (Card Border) and another one is everything else except the border (Track Card). And added a Card Content named slot inside the border widget:

Screenshot 2023-08-12 at 16.14.13

  1. Updated the Track Card blueprint by adding Parent: Construct at the beginning:

  1. Inside the Card Border blueprint I added the part of adding a child to the Card Content named slot:

But something is still wrong. I tested it on the Pre Construct event and saw that it works, the child is added to the named slot and it shows the default image there. Also, when running the game, variables, from each of 4 cards are reading (checked with the Print String at the end of each Track Card blueprint). But cards are not populated with images and I keep receiving the Accessed none errors for the Card Content named slot:

Screenshot 2023-08-12 at 16.12.43

I feel that I’m doing something wrong but couldn’t find an answer, probably it’s not even Named Slots related problem, since I received the same error while adding children to another component, such as scale box. Any clues? :pleading_face:

After some time of changing everything with a hope of receiving positive result I’ve found the reason it wasn’t working.

I added validation before adding a child and all errors have disappeared:


h

Not sure why, trying to understand it now.

And the reason why there was no images is also weird, they were there, as all other data I mentioned in my previous message, but due to it’s anchor settings it was stretched somehow that it appeared outside of the box where it should be rendered. So, I wrapped it with a scale box and now it works perfectly.

@Everynone thanks for the suggested solution. I managed to get close to what I wanted :wink:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.