EDIT This tutorial is out of date as of 4.7, now you can just use the WidgetComponent and change the new Space property to “Screen”, will do all this work (and more) for you.
====================================================
Matt and I did the support twitch stream yesterday and several people were curious about how you get widgets to appear over actors in the world, but in screen space. NOTE: The widgets are not actually rendered in the world, they’re still in the viewport.
DEVNOTE: I didn’t noticed until I finished writing this tutorial that you can’t expose on spawn Text variables in 4.5, coming in 4.6 When you get to that part in the tutorial, just replace that with, “Make a function to set the text, or make it public so you can set it after spawning the widget.”
First we need to make a user widget that we want to appear over our actors, mine looks like this:
I deleted the Canvas, because I don’t want absolute layout, I just want something that flows and has a desired size. So I placed a Horizontal box with some text in it. The text block is bound to a Text Variable I placed on my widget class simply called “Text”.
Next, we need some logic for this widget. On construct, we’re going to set it’s alignment in the viewport to be 0.5, 0.5. When UMG adds items to the viewport, it’s constructing a temp canvas to house the widget in. Normally we anchor the widget to fill the entire space, but setting the alignment and position manually lets us position our user widget inside that temporary canvas just like we would in the designer. The Alignment is more or less the normalized pivot point in local space of the widget about which it’s positioned. So by setting it to 0.5,0.5, we ensure the horizontal box + text will be centered about whatever position we give it.
Additionally - each Tick we determine the position of “Ammo Box” which is just a member variable we exposed on spawn for our widget that the Ammo Box actor that will be creating this widget is responsible for setting. We transform that position, plus some offset, to be in screenspace. Then we set the position of our user widget in the viewport, we don’t worry about also setting the size, because by default widgets will be their desired size when using absolute position in the viewport.
Ok, now we need our actor to construct our widget. I made a simple ammo crate static mesh blueprint actor, and on his begin play he constructs my AmmoContainerUI widget, assigns himself to the Ammo Box exposed on spawn parameter, as well as a Name Variable, is assigned to the “Text” variable that is also exposed on spawn that our textblock has a binding to. I assign the UI to a variable that the actor keeps track of so that he can remove it from the viewport when it is destroyed.
And here’s what it looks like when it’s running,
Cheers,