Scene Actor's bounding square (screen space)?

Before I start trying to reinvent this wheel, is there an existing combination of nodes that can be used with the (2d) DrawLines UMG node to draw a 2d bounding square around a scene actor?

An example of the desired end result, is shown in screenshot.

I attempted to convert thetriponator’s C++ code as shown here:

but ran into problems where Box2D is used as there are no equivalent Box2D.Min / Box2D.GetSize() functions in blueprint. There is a Box2D type in blueprint, but it seems to be lacking functions.

I tried creating equivalent Box2D functions to store min/max values when iterating over the 8 bounding box points
but couldn’t get it to work.

Cheers.

4 Likes

Hello,

I cannot reproduce the tighter fit bounding box solely in Blueprints, but I can get you everything after that point, and the simpler 3D-bounding box in 2D space method:

For this example, I simply create the widget in the level BP, and assign it to my Actor.

294294-figure1.png

Level BP:

Next in the widget, we create an override function for OnPaint, that draws a box from the top left corner to the bottom right.

Overriden Function in Widget “OnPaint”:

Most of the heavy lifting goes on in the widget blueprint’s event graph. First we calculate the 8 vertices that make up the 3D bounding box.

I have a debugging method to visualize these points, but you can skip or disable it as you see fit. I’ve run out of screenshots, but you can see it in the BlueprintUE link.

Next we convert these 3D points into 2D points on screen. (Its worth noting that if you can find a way to get a more accurate series of points representing your mesh, such as socket that you place at the extents of every joint, you can leave the rest of the code unchanged.)

Then we recalculate the box by finding the uppermost point, and the leftmost point, and combined them to make the top left corner. Similarly we find the rightmost point and the lowermost point and combined them to make the bottom right corner.

Widget Event Graph:

Once thats all set up, you can test the effect by running play-in-editor
Here is a video sample of the end result:

4 Likes

Missed one, sorry. Be sure to reset the BoxStart and BoxEnd variables as shown here just before you recalculate the box.

1 Like

Hi Ian,

Your solution worked out great!

I had 50% similar (ish) scripting so didn’t have to re-script everything, but the most important part was the ‘box calculation’ (Uppermost / Leftmost / Rightmost / Lowermost points) which is where I got stuck. Your screenshot solved my problem so thanks for that.

Just so I can add a note for future reference: can you briefly explain why the local/absolute size multiplier was necessary?
i.e.,

[Get Player Screen Widget Geometry].GetLocalSize()

[Get Player Screen Widget Geometry].GetAbsoluteSize()

I would never have thought to use the local/absolute division as a multiplier, but noticed that the bounding rect does not work without that multiplication.

>I cannot reproduce the tighter fit bounding box solely in Blueprints, but I can get you everything
>after that point and the simpler 3D-bounding box in 2D space method

The loose rect solution is fine for my purposes as it is only a general ‘region tracker’ and doesn’t have to be exact (for now).



>(Its worth noting that if you can find a way to get a more accurate series of points representing your mesh,
>such as socket that you place at the extents of every joint, you can leave the rest of the code unchanged.)

If I later need a tighter bounding rect I’ll probably experiment with a sphere (capsule?) trace to get the points representing the furthest hit extents on an actor’s mesh (top/bottom/left/right from the camera’s view) . I could then project those four points to screen space, calculate a rect and draw the 2d bounding box. Not sure if it would work, but would be a good place to start.

Cheers!

I’m glad it worked for you!

“why was the local/absolute size multiplier was necessary?”

I set that up on a hunch. My 2D box was initially offset and too large. When I changed the viewport size, the size of the box changed with it. Based on this info I knew that the unit size of the 2D space was missing a multiplier to shrink it to match my viewport size. The division of local widget geometry size by global widget geometry size is finding the percentage of the screen not taken up by editor window widgets (I assume). This would not be necessary if my widget geometry took up the full screen, which it probably does in Standalone Window mode.

Noted.
Thanks Ian!

Hello,
This message was completely edited, because of my mistake/s.

AFTER 3 YEARS THIS SOLUTION PROVIDED BY @anonymous_user_1ed03e56 STILL WORKS GUYS

Why It didn’t work for me in the first place:
I was constantly testing your solution using “SIMULATE” instead of normal “PLAY”

Why It started working for me:
I was using SIMULATE as the way to test my project, fly in the area really quick and so on. And it was a real problem here for me, because apparently in simulate mode my viewport camera was stuck in one-starting place constantly, which means my active camera-viewport wasn’t couting towards the calculations. Strange, isn’t it?

When I started using a “play - selected viewport” or just “play standalone game” everything started to work fine for me.

I was constantly simulating, because it was really convinient just to fly around the map with the speed of sound, instead of slow paced flying and this is the thing that got me a problem.

Simple graph showing of the problem I encountered while using Simulate:
I was printing the viewport X/Y was a static car and I was constantly getting one set of results no matter how hard I was changing the view of my “active” camera I was flying with. All calculations were coming from the “start” position, which is “static” camera in the picture. Using different way of starting the game like “play in the viewport” (everything else apart from Simulate) was correcting the camera position and making calculations from the active position I was holding.
Solution_Graph

Here is the screen of working solution.
As you can see there is a small delay for debug (red) points, but the solution works and I’m grateful. Thank you lan :slight_smile:

Hi, I tried to do the same thing that was written here. But when the project starts, nothing happens. Can you tell me what is the reason?

Hey,
Are you sure nothing happens?

Did you connect your actor to the widget as an entry during it’s creation?
Did you add “Add to viewport” method after Creating a widget?
Did you run your project using play standalone game?

Cheers, V.

Hi, I don’t have enough knowledge about blueprints to get a working blueprint easily and quickly. But I was able to draw dots on my box. Then I don’t know what to do. For example, how to add an Actor input value to the Create Widget. There is also a question about OnPaint, I couldn’t see where this function is used, maybe at the end, but after doing the loop in the Widget, I’m wondering what should go next, because there’s nothing there.

Best regards, .
P.s. I’d like to post screenshots, but I’m getting some kind of error…

Okay, no problem. I was there too :slight_smile:

  1. Drawing dots on your collide box is a very good step. You clearly see where are drawn extends of your objects. Those extends are important, because we choose 4 from them:
  1. The highest
  2. The lowest
  3. The one furthest on the left side of the screen
  4. The one furthest on the right side of the screen

In the next step we merge these points. The points in 3D space are converted to 2D space on your viewport. Top left corner of your viewport is a point XY (0,0) and bottom right corner of your screen in editor is XY (Max Resolution X, Max Resolution Y). For example resolution of my viewport is 1280x720, so bottom right corner will be XY (1280x720).

We merge points by combining their X and Y coordinates.
For example (picture below):

  • The highest point is the blue one so we take it’s Y (the smallest Y),
  • The furthest left is green point, so we take it’s X (the smallest X),
  • The furthest right is orange, so we take it’s X (the biggest X),
  • The lowest point is a red points, so we take it’s Y (the biggest Y).

So the TOP LEFT corner will be Blue_X, Green_Y,
the BOTTOM RIGHT corner will be Orange_X, Red_Y

And as you can see, green+blue+orange+red lines create a rectangle, which in the end is known as the Bounding Box.

Test

2. To add Actor input to your widget or any other variable

you need to get inside of the Widget Blueprint and ADD the variable and select few checkboxes. In our case it’s an Actor variable type with the same name. But If you want an Integer or something other than Actor then the rule is the same.

After you selected the Actor variable type, select:

  • Instance Editable,
  • Expose on Spawn,

Instance Editable is required if you want to have an Input to your widget and allows you to edit your variables if you would like to use your widget by another actor for example.
Expose on Spawn on the other hand is a target of your question. By exposing variable we treat it as an input to that widget :slight_smile:

After we checked boxes hit Compile and save. Now, go back to your object where you want to input your Actor.

If you don’t see Inputs press Right click on the Create Widget node and hit REFRESH NODES.

If your Variable is “Actor” then you should connect Actor itself, that’s why do a right click in the free space of the blueprint and type “Self”. You should be able to find “Get a reference to self”. Click it, connect it to the Actor input we just created and that’s all!

// As you can see I allowed myself to Expose even more variables like ID, Hours, Minutes and so on (Integer variables).

//Make sure you connected all “Add to viewport” node otherwise you won’t see anything on your screen.

If you haven’t modified much code provided by @lan, then it should pretty much work from now on. Just make sure you don’t use “Simulate” to test bounding boxes.

.
3. Function OnPaint is an override function. It works ALL THE TIME. You don’t have to worry about connecting it or calling it, because that function just does it alone by itself constantly.

If your Bounding boxes are correctly calculated then you’ll see a rectangles through your map if you face your target object with your viewport camera.

If your Bounding boxes are not correctly calculated then you won’t see any drawings, but in real scenario they will be still calculated and drawn.

Hope it helped :slight_smile:
Best regards,
V.

Edit:

  • I forgot to mention that Top left corner of the Bounding Box is called (in a code) “BoxStart” and it has the smallest X and Y.
    “BoxEnd” is the Bottom Right corner of the Bounding Box which is known as the biggest X and Y. Good luck!
1 Like

YEEEESSSS!!! I did it, I I succeeded. I added an actor with your advice and found the problem, now everything is working. Many thanks for the help!!! :grin:

1 Like

Glad it worked for you. Take care.

Kind regards,
V.

Hey VtojeC_V, I used your advice as well thanks but for some odd reason the top left of my bounding box is super stretched out. Do you have any insight on this?

1 Like

Sorry for the late reply.

I admit, I also had some problems related to objects which had weird looking collision.
For example for the car shown in the picture I uploaded in previous post all corners of Bounding Box are okay, but for some reason when I tried doing the same with MetaHuman it had really weird bounding box.

In that case I remember I went into my actor components and set something with collisions and then it started to work properly. I’m sorry I cannot provide you any picture, but for now I am unable to use Unreal Engine. Try to mess with some components settings to solve that problem and see if anything helped.

The second solution I personally used was decreasing the multipliers of X+/Y+/Z+/X-/Y-Z- in Bounding Box generation. You see, this code generates 8x extends from which bounding box is created so our job is to make sure those extends are not going too far.

I’m trying to say you can modify “manually” the multipliers which create the “distance” of the extends. By putting lower values than “1.0” presented in the original code you can SPLIT STRUCT the vector for certain extend or extends to obtain a possibility of modifying it’s values.

This is a trick I did in my project to “tighten up” a bounding box. Look at the picture I provided below. I splitted the vector into floats and then connected them with float variables like ~ 0.63 to tighten the Bounding Box - making it being closer to the targeted object. I think you can try do the same.

(I’m sorry for the low quality picture.)

I’m sorry for the late reply. 2 weeks has passed and I’m convinced you have found your solution by that time. I’m replying so other people can get a solution if they need it in the future.

1 Like

Add a box component or get the Capsule Component with “get component bounds” instead of get actor bounds may more easier to adjust the final wire frame effect.

Thanks.

1 Like


HELLO,
i couldnt assign the Widget to the Actor. Has anyone else had problems on this step ? im running UE5

Hi,

has anyone achieved this without “Add to view port”?

I’m trying to apply this to VR and “Add to view port” doesn’t seem to work.

How can you add pins to your CreateWidget Node ?

Go inside of the Widget Blueprint and create new variables. Then check the box “Expose on spawn”.