Download

[UMG Tutorial] - Placing Widgets Over Actors In Screenspace

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 :slight_smile: 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:
TextOver_TextWidget_Designer.jpg

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.
2851a5b9f3110e2d1a963271d3f73aba875c04cf.jpeg

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.
TextOver_Spawn.jpg

And here’s what it looks like when it’s running,
430dcd0e53210d77e2ef8ee3be23a384421fc8b1.jpeg

Cheers,
Nick

Sweet, thank you much for this

hi,
thank you for this clarification , I think we’ll do great things in Unreal 4.6
Love stylised character…

Thank

Hey thanks for this. Very much appreciated!

Thanks Nick, I did your tutorial. I got a question, though, how can I put the text location only on top of Actor (like the using UTextRenderComponent then rotate and move them relatively based on Character’s camera’s and Actor’s rotation and location). Right now, The text located fix on the screen even if I rotate away from the Actor.

Is this method more performant than using a 3D component-based widget? This seems great for drawing on top of everything when necessary but i can’t seem to find a way to occlude the text. A 3D component widget seems not only easier to use, but like it would be occluded by objects in front of it. Unless I’m wrong?

Yes - much more performant. The Experimental :slight_smile: 3D widget currently employs a render target in order to be rendered into the world. So for every one of them, you’ve got another render target. On top of that, they’re in the world. Which means they get all the same post processing everything else does, motion blur, AA shader…etc. so if the camera is moving, don’t plan to be able to read it. You are correct about the occlusion though, it’s good for making Dead Space styled UI, where the camera is stationary.

You want the text to rotate when the object rotates? That’s a bit tricker, you’d need to figure out the render transform to apply to get the same rotation in screen space. I would just use the text component if all you need is text and wanted rotations to be applied.

Thank you, Nick. I’m excited to figure out different ways to employ this :slight_smile:

So unfortunately this method fails when r.ScreenPercentage, or sg.ResolutionQuality are not 100. Any tips to have this align correctly under those circumstances?

I’m having the same issue! Any workarounds?


To reproduce, do the following:

  1. Lower the resolution
  2. Close & Reopen the project
  3. Play

Edit: This was apparently reported here, under bug report UE-6191.

Edit2: By the way, is it possible to occlude these widgets behind other UMG widgets?

You’d need to get the resolution quality and divide the projected position by the normalized quality.

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”.

I’ve just checked in a fix for the quality issue, and extended the capability to control the ZOrder of the widgets added to the viewport, for both the standard BP call, as well as the WidgetComponent. Which will allow you to control what layer they appear on LHutz. Those changes should be in github master soon / 4.8.

Thanks a lot Nick!

Wow, I can’t believe how simple this is! There is still the resolution problem but we can wait for 4.8 for that.

Thanks!

This is a great tutorial. I had a perfect way to do this same thing in 4.4 that would parse strings and display them over an actor’s head (think SCUMM era dialogue), but with UMG it became obsolete and this method is way (re: WAY) simpler. No math involved!

Thanks!

Thanks for sharing this with us Nick!

[FONT=Comic Sans MS]:heart:

Rama

Thanks for the tutorial.
There is one interesting thing I run into during recent development.
I don’t know if here or the answer board would be better place, let me know.

  1. I finally figure out a way to make class dependent custom context menu, so class A have it’s own menu item say a spinbox and class B have a combo box instead.
    But during this development, I found it’s only possible through event dispatcher so that each instance gets to keep their own data and event feed back from the widget.
    I wonder if there is a better way to implement this in blueprint? So a struct in a blueprint can let a widget blueprint to setup the interactions.
    My original thought is to use construct to take in a reference and the use a struct from the actor to build dynamic menu(with different widgets), but found it really hard to pass result back to the actor.
    So at the end I do it reversely to let the actor build and add its own widget and use event dispatcher to bind UI events.

  2. there doesn’t seems to have a mouse scroll events on slider or spinbox widgets. Which seems to be a pretty good interaction method for UI in many softwares, but not in UE4.

  3. is there anything that we can do to have a proper “text bubble” or “chat bubble” style of pointy widget that point to certain location in screen space?
    Like the word processor/slide making text bubble that you can drag a yellow dot and the pointy wedge shape will have a good visual reference for player?

Thank you!

Sorry to bump this but this is very close to something I’m trying to do.

This tutorial is great! That is until you try to move the object the UI is placed on.

Is there any way to get it to follow an object?

Hello,

i have 2 questions about your example.

First: Regarding your Hotfix Video, to avoid circ. dependencies, you call Get Player Controller inside a widget, which is exactly, if im right, the problem can can cause those. And that
is why i am using delegates for this OR maybe i would replace the Get Player Controller with Get Owner.

Second: the function convert world location to screen location. I assume it is referring from Get ViewportSize inside the PlayerController. If that is right i would like to know if this is working
when you play that game in Standalone mode. I am asking this, because i posted a bugreport on answer hub, experiencing the issue that GetViewportSize returns 0 in Standalone. Maybe this is an hardware issue, but
im curious if you have the same problem like me.

best regards
Wallhalla

Hi Nick i try to do this in 4.7 but no luck, I don’t know how to use the widget component. Also I have a little issue and also I don’t know why, maybe you can help me. The issue is , the text is not displayed at the top of the object, is slightly offset to left side and fly around.

This is the way I try to do it with Widget Component on my pickup blueprint: (I also added a widget component and assign to it my text widget)

&stc=1

This is the Text widget: (when I use the “new” way on my pickup blueprint for show the widget I also try to disconnect all the events on the text widget)

&stc=1

This is the Offset I mention:

&stc=1

Maybe you can show us how to do the same in 4.7?

I hope you can help, and thanks in advance

Based on the screenshot, it looks like maybe your editor kicked in scalability settings? I’ve noticed that world to screen functions get messed up if the editor does a resolution scale, which can happen automatically during times of poor performance.