How to add nonvisual components to UserWidget

Long time Unity dev moving some work over to Unreal.

A pattern we use quite a lot in Unity is building out UI using small, reusable components that implement UX logic (say timers, network calls, etc.). We add these components to the UI Game Objects to drive the UX. This allows us to quickly built up fairly complex UIs without having to write a lot of specialized code.

I’m trying to find a comparable in UMG. It seems like I can only add other Widgets to my User Widget, and they always want layout properties, etc. One option would be to just stick these in a container that doesn’t render, but this seems like a hack.

Is there a way to attach more generic objects (say derived from UObject) to a UserWidget? Would this be the domain of a custom Blueprint node?

Thanks!

You can add variables to your widget just like any other class/blueprint.

I’m not sure how that helps, I’m looking to add additional components to the screens to break up the logic for the UX. In Unity I can attach any number of MonoBehaviours to the screens and have them operate independently.

One example might be a reporting component that sends information about the panel that was pushed along with the data that was sent to the panel. It’s attached to the lifecycle of the panel, but doesn’t have a visual component.

Another example would be a screen that is managed by two separate components (say trivially a timer + something that displays an image). We could have a reusable “timer” component and a reusable “show image” component. (This one is overly simplistic because each of these could probably use be User Widgets, but for more complex layouts this sort of modularization has been very helpful.)

I may be missing something and if so I apologise, but what you are describing just sounds like composition to me, a very common pattern that is naturally supported by any language that supports object oriented programming.

Put your ‘behaviours’ in their own class/blueprint, then add them (as variables) in the widgets you wish to use them in.

Thanks for bearing with me here…but I’m still not sure I understand how adding variables for these components allows me to do this. You’re exactly right that what I’m trying to do is compose functionality out of a bunch of reusable components.

I tried adding a variable for one of the components, but all I can do is get or set it–I don’t see any way to leverage the functionality that the component provides. I am very new to Blueprints so may be missing something obvious.

What I ideally want is to add these components to the Widget same way I can add components to an Actor. It seems like I can only add other Widgets to a Widget though.

Ok, I see how I can instantiate a component and make calls to it via Blueprints. Ideally the component could take on a more “proactive” role like the other UObjects do when they’re attached to an Anchor. This approach feels like it will generate a lot more overhead than just adding a component to a screen and having it react to the lifecycle events of that screen. But maybe I can find some simplifications.

Not sure how helpful any of this will be, the examples uses given have all been pretty simple and nothing that really warrants splitting anything out into a re-useable class (except perhaps the panel one, which I don’t understand so can’t really comment on).

Whatever functionality you want from a timer can possibly be achieved just using Delays, and if you need something more timer like, there are actual Timers too.

Making network calls in widgets seems like an architecturally unsound idea (coupling networking functionality to the UI), but that is of course highly dependant on the use case. In general I would want my networking code elsewhere, and just call it from the widget event, so that it could be used from other places (in response to some configured ‘hotkey’ maybe). Perhaps there are other cases where what you would have put in one of these behaviours might more sensibly live elsewhere, and be called from the widget.

As to your own component like system for widgets (using variables), you could build something to support at least some of the things you want, but I would first question the need-for / desirability-of it.

I’m not entirely sure what you mean by lifecycle events, a variable will be destroyed with it’s owner automatically.

If you want to pass events between the widget and it’s ‘components’ you could look into event dispatchers, or for something more ‘automatic’ (if you are just talking about forwarding events to the components) then you could make an interface for the components to implement, BPI_WidgetAddon maybe, and your own UserWidget derived base class, say WBP_UserWidgetWithAddons that manages a list of addons (add, remove functions) and calls the appropriate functions on them when events occur (this requires some one off work up front to set things up, and also a small effort on use for the components to be initially added, so perhaps not really so automatic, but if you have a consistent set of events you want to broadcast to components would be less messy than event dispatchers).

While I used Unity briefly many years ago, I do not remember much of it and am not sure just how different things are between these two worlds, but it might be advisable to be searching for / asking about solutions to specific problems to see how other people are solving / would solve them, rather than looking for exact analogs to things you were doing in that other world.

These were deliberately simple examples to avoid getting into a lot of detail. Network code of course lives in services classes, what I’m talking about here are UX components that initiate/consume the network requests & results (e.g. a login page). Variables + events works in Blueprints, it’s just a lot more cumbersome than doing the same in Unity. What’s nice about Unity is everything is just a Game Object with MonoBehaviours, so there’s no difference in setting up a world object vs. UI objects. Components can go anywhere and reference any other components. With Blueprints there’s a lot of churn to set up the same associations, at least from what I’ve found so far.

But fundamentally the answer to the original question is, “No you can’t stick a UObject onto a widget,” which is quite limiting. You’re either a widget or not, so you have these two worlds of code that need a lot of plumbing to connect to each other.

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