Get Owning Actor of UI Widget?

Hi all,

I’ve just added a UI widget to my NPC. I want to be able to access the actor from within the UI widget in order to get a hold of a component (health) so I can update the progress bar.

I’m not seeing any intuitive built in methods like “Get Widget Owning Actor” etc… I’m guessing I may need a few steps but I’m not sure what they might be.

I’ve had a little look online and the closest I’ve come to a solution was an article in which they have a variable on the Widget and then set that widget within the owning actor, setting it to “self” etc… but that feels really kinda, well, clunky…

Any help would be appreciated :slight_smile:

1 Like

Many ways to do it.

You can create a direct reference to the parent actor (self) inside the widget:

And then make something magical with the widget’s text block to display it:

Any changes to the cHealthComponent’s PlayerHealth variable are now reflected in the widget’s text block. It works fine providing you keep things safe - as in, do not destroy the actor, otherwise the widget will start feeding on the null OwningActor reference. [HR][/HR]
You can have the actor pull data from the component and feed it to the widget. The widget has its own custom event (UpdateHealth) and handles it accordingly, setting and formatting text.

[HR][/HR]
Another method is to have the component broadcast data via a dispatcher (does not have to be on Tick, of course - event driven is preferable where applicable):

The actor’s job here is to hook up the dispatched call to a custom event (with a matching signature) in the widget, creating a listener of sorts. This works well; if the widget gets destroyed, the broadcast keeps blasting but no one is listening; if the actor gets destroyed, the widget is listening but no one is broadcasting. No harm done.

You can bind and unbind events from dispatchers dynamically.

edit:

You can also update the native widget elements directly:

I generally try not to make widgets responsible for too many things. Widgets can format incoming data and set children properties but I’d avoid giving them direct access to actors.
[HR][/HR]
And there’s this thing, of course. As seen in many tutorials.

Many widgets allow for property function binding (or just a variable, which is fine). These get executed every frame, not a fan. And you need to slap *isValid *everywhere.

Hi,

Thanks so much for this, especially with it being so detailed… its almost what I want, but not quite…

So, I am trying to wire up an event from an event dispatcher… the event itself is being broadcast from another component on the actor. So, I have a widget and a component on the actor. I want the widget to be able to bind to that event, and that’s where I need the actor reference. In your examples above they are all being performed outside of the widget, on the actual actor, with perhaps the exception of the first screenshot, but in that one it looks like your creating the widget, where-as I have it as part of the blueprint class in the components hierarchy, e.g. I added it manually.

Your final example is the closest to what I have/want, but I would prefer to put it in the widget, not the actor. So, from within the widget, how would one look “outside” or “up” so to speak and get that actor reference?

Note - I’ve just re-read your post and saw your comments about not giving widgets access to actors and just letting them receiving data and output etc… sounds like a good idea, however, my PlayerHUD has access to the player and all of its components, so I feel if I was going to change that as an architectural design consideration now, I’d also need to change that PlayerHUD, which I don’t really have the time to do - at least not right now. Will deffo consider this going forwards though and for a refactor.

2 Likes

You must be talking about widget components. A component that owns and automagically creates a regular widget and shows it in either world or screen space.

With any component it’s actually easy, all you need to do is to Get Owner, and cast.Annotation-20191213-195522.png

The widget component does not have a graph so not sure if I’m getting what you need. [HR][/HR]
Also, updated my previous post but those are not the example you’re looking for.

edit:

Or perhaps you have an ActorComponent that creates a widget?

Hi,

Yeah, it was a “Widget Component” I added to the actor… I have just tried calling a method on it from the actor, in a similar fashion to your examples, but I’m running into so many problems now its unreal (excuse the pun)…

I have a “widget” called “Health” which is the little bar that should show above the NPC. I have added a Widget Component to the actor and set the Widget to by “Health”. When I then try to call a method within that I’m getting issues because Health isn’t of the same type and doesn’t inherit from Widget Component… Gah… I was hoping this was going to be like a 5 minutes to add feature…

I have tried the “GetOwner”, but that isn’t available within a Widget. There’s not a “GetOwningActor” either. All I can get is a “GetParent” but that assumes it will be another Widget…

:frowning:

Update…

I have managed to call the custom event within the widget finally… in the blueprint for the actor, where I’d added the WidgetComponent, I dragged that into the graph and from that use the “Get User Widget Object” which gave me my “Health” widget… from that I could then call my custom event within it.

So, I think I’m in a place where, I can update it now… albeit it not how I would have liked, and the design is now different from how I’ve done the player hud… but if it works it’ll do for now…

Update 2…

Yeah, this is an utter mess…

Because my actual Health component is being added in the construction script, the first call to the OnHealthChanged event is missed by the widget, because it isn’t being setup to receive those messages until BeginPlay. I figured I’d move those nodes to the Construction Script… I can’t do that either…

I can’t “Create” the widget, because you can’t do that in the Construction Script apparently, only from BeginPlay etc… I can add a “WidgetComponent” within the construction script, but then not set the user widget I want it to use, for some reason nothing appears within the “Assets” display/search.

So I’m left with a really messy situation here… I cannot believe this is so difficult, and can see why now in that article I saw they just dumped a variable in the widget and then set it from the actor to get the reference to the actor.

Update 3…

I have something working now, its not exactly as I would like it, but it is working. I have taken what you suggested about having the widget just updating the display, and used that approach, so the logic/code is in the actor blueprint, and it just fires through a value to the widget. I had to change a few things around with my use of the construction script and add the health component manually in the blueprint, but now those changes are made, the event is responded to correctly when its fired.

Thanks for the suggestions and taking the time to reply @Everynone, appreciated :slight_smile:

In case there are someone, who is looking for a solution to get parent actor from 3D widget.

Instead of creating widget using 3d widget class in settings, you can create it manually using Construct Object From Class. Pass object to Outer pin. Then you will be able to get actor from widget by using “Get Outer” node.

You can then cast outer object to a class of your actor or call interface on it.

Using this solution, you do not need to create variables inside a widget and expose it to creation node, which makes it more flexible. In addition to that allows you to create different widgets of different classes dynamically.

1 Like

You can also override the widget component which gives you more control over its behaviour and then:

Now you have scenario where the widget embedded in the widget component talks to the owning actor via a dispatcher. And the component itself also gets a say! This gives you a chance to run an abstract layer of logic the underlying actor may not want to care about.

Careful with this, I discovered a bug which is ignored…:

[Bug Report] Adding UWidget causes widget tree corruption