"Get actors in selection rectangle" doesn't work?

Hello everybody,

I try to make the “Get actors in selection rectangle” blueprint function to works …

I’ve tried by taking 2 points on the screen with the “Get mouse position” blueprint and tried with 2 points on the world but it has no effect, that does nothing …

When I print the coordinates (with world coordinates and screen coordinates methods) it prints the right coordinates on it.

You can find the test blueprint with this message.

If you have the solution or an idea … thank you :wink: !

From what I can see, you’re not calling “set” on your “Actor Array”.

Make sure it’s part of the execution flow by connecting it with the white lines.

Sorry, moved these to make the screenshot, it was connected when I tried ^^. I don’t know why it doesn’t work …

connected where? you should show a screenshot of the actual blueprint

#Working BP Setup

Dear Everyone,

Here is a BP setup I just made to illustrate how you can use Get Actors in Selection Rectangle in 4.4

It is important to use a local variable, and thus you should put Get Actors In Selection Rectangle in its own function.

Once my github pull request is accepted this step will not be necessary, in future builds

https://github.com/EpicGames/UnrealEngine/pull/370

#Why Local Var?

When I wrote this node I did not anticipate that the output array of a BP node would count as a global variable, and so directly plugging the output of the node into the for each results in an ever-growing loop that accrues each tick.

As I mentioned I’ve already submitted the fix on github, so this will not be an issue in the future, once that pull request is accepted.

This was a function I wrote for CPP and BP, and I did not know this nuance of BP output arrays,but now now I do!

#Customize Function As Desired

Please note this is just a BP to show how to use the Local var, to avoid accruing a large array that stalls the editor.

Please customize the BP to your actual needs, this example just goes from top left of screen to wherever the mouse is.

#Enjoy!

Rama

Hi Rama ! Thank you for your answer !

First, it seems to work better than what i’ve done before ;). But there is something strange : When I do a box selection, it seems that the function detect the actors even if I am far from them … and even if I tick “Actor Must be Fully Enclosed” on the “Get Actors in Selection Rectangle”.

I’ve made 3 screenshots to show you what’s going on when I try to select them (at the left there are the first point, the second point and then the coordinates of the 2 actors), the blueprint that show the function where the “Get Actors in Selection Rectangle” is used and the third blueprint that show how I get the first and second point.

Maybe I have to convert the screen coordinates to the world coordinate or something like that ?

And the third :wink:

#Fully functional BP Setup For You

Dear Footy,

I am providing you with pics of a custom PC BP and HUD BP illustrating how you can get selection working properly from any angle / having any first anchor point.

I’ve just created this setup for you and I know it works from my testing :slight_smile:

For anyone wanting to try this, just go to window->world settings and create a custom game mode

you can then assign custom Player Controller BP and HUD BP to the new game mode.

You can set the Pawn to Spectator pawn so you can move freely with camera and draw your selection box (I did not actually draw the selection box in the BP code below)

#PC BP

#HUD BP

#Final Step

The final step is to do a branch in the main HUD BP to only call the Selection BP Function if Should Draw Selection is true

#Enjoy!

Rama

Thank you Rama, it is very kind of you to spend so many times for me ;).

I have made the same BP as you and there is still this problem : the actor is detected before I touch it.

On the first screenshot, no matter where I click on the screen, the actor is selected.
On the second screenshot, when I click in the black rectangle (no matter where in this rectangle) the right actor is selected.

I have looked in the mycharacter BP (I used the one that is given with the third person BP when you create a new project) and I see nothing that can explain that …

#For Testing

For testing purposes can you use a series of small static mesh boxes or other shapes?

arrange them in a grid on the ground or wall

and test with that?

we need to narrow down the issue

I got the above use case working perfectly, and so I want know wherein the complication lies

Once you try my example let me know of your results!

Then we will know better how to tackle the character mesh case

#Most Likely Cause

I am inclined to think the issue is because the default implementation was made to include all components

//Get Actor Bounds				//casting to base class, checked by template in the .h
		const FBox EachActorBounds = Cast<AActor>(EachActor)->GetComponentsBoundingBox(true); /* All Components */

This should be made into a parameter option so you can decide whether to include only colliding components

#I think you are picking up the camera as part of the box

Rama

Oh ! Thought it was only taking the Actor !

I have not the camera in the component. But because it is a “Character Blueprint” it has an “ArrowComponent” (that I can’t delete). I don’t know what size is this component because when I look in the “Component” part of the mycharacter BP and if I zoom on it, the arrow is little but If I zoom out, it becomes tall.

If the “Get actors in selection rectangle” select the arrow as a part of this actor, it can be the problem (as we can see on the screenshot posted previously, the black rectangle is in front of the character (where the arrow is) not behind.

I have made a test with some Shape_Cube and it works fine :slight_smile:

I added a camera (in the mycharacter BP’s component part) for a quick test, and it made something strange … as you can see on the screenshot, no matter where I click in the red rectangle, mycharacter is selected …

#Github Changes Made

Dear Footy,

Improvements have been made to get actors in selection box and will be in a near future engine version!

Github link
https://github.com/EpicGames/UnrealEngine/pull/370

Let’s revisit this after the changes get integrated! I am not sure if it will be 4.5 or not, but it will be soon :slight_smile:

Rama

Thank you Rama :wink: such good news are always welcome :smiley:

Hey Rama, is there any (good) reason why the node is only allowed to be called from the “DrawHUD” Event? I tried to call it from outside and I get the warning “Canvas Draw functions may only be called during the handling of the DrawHUD event”. It’s clearly not a “draw” function. I could imagine that it could only make sure to use valid values while it’s in the DrawHUD event, but I would not have a problem if it would just use the values from the last tick instead. Is there any way how I can use the node outside of the DrawHUD event?
Actually, I just want to use it for getting all actors which are currently visible on the screen, so I created a function for this in my HUD which I can call from any other blueprint. As a workaround I could just save all the actors visible on the screen every tick in an array in the HUD, but I guess it would waste a lot of performance.

Hi Footy,

Were you able to solve this problem? I’m facing exactly the same one, the actor is selected before the box touches it :confused:

Any help would be appreciated!

Thanks in advance!

Can someone confirm if this working in 4.11?
I’ve got similar setup and whatever I do (including local variable in function) array is always empty with one exception - when I try to fill UMG with its content - but when I try to set it as a variable in that umg it is empty.

It does not working, the function pick up the actor which is outside the selection box.

(lengthy source code snippets below, beware…)

I had a similar problem, in my case it was all the different components I had on my pawns that were inevitably expanding their bounding boxes to beyond what I’d expect. My solution was to subclass AHUD::GetActorsInSelectionRectangle and simply remove checking for anything but the root component. Since Pawns and Characters in general only use their root component for collision anyway, I think my approach makes sense. This got it down to 99% precision.

It’s very similar to GetActorsInSelectionRectangle(), in fact all you need to do is copy-paste the whole thing and replace this one line:

const FBox EachActorBounds = EachActor->GetComponentsBoundingBox(bIncludeNonCollidingComponents); /* All Components? */

with this:

const FBox EachActorBounds = EachActor->GetRootComponent()->Bounds.GetBox();

Just for clarity’s sake I’m including the complete function below, .cpp and .h. Hope this helps!

Here’s the relevant part from the .h file of my custom HUD class in c++:

public:
	// Similar to GetActorsInSelectionRectangle() but only takes into account the root component of each actor.
	UFUNCTION(BlueprintPure)
	void GetActorsInSelectionRect(TSubclassOf<AActor> ClassFilter, const FVector2D& FirstPoint, const FVector2D& SecondPoint, TArray<AActor*>& OutActors, bool bActorMustBeFullyEnclosed = false);

And now for the .cpp:

void AYourHUD::GetActorsInSelectionRect(TSubclassOf<class AActor> ClassFilter, const FVector2D& FirstPoint, const FVector2D& SecondPoint, TArray<AActor*>& OutActors, bool bActorMustBeFullyEnclosed)
{
	// Because this is a HUD function it is likely to get called each tick,
	// so make sure any previous contents of the out actor array have been cleared!
	OutActors.Reset();

	//Create Selection Rectangle from Points
	FBox2D SelectionRectangle(ForceInit);

	//This method ensures that an appropriate rectangle is generated, 
	//		no matter what the coordinates of first and second point actually are.
	SelectionRectangle += FirstPoint;
	SelectionRectangle += SecondPoint;


	//The Actor Bounds Point Mapping
	const FVector BoundsPointMapping[8] =
	{
		FVector(1.f, 1.f, 1.f),
		FVector(1.f, 1.f, -1.f),
		FVector(1.f, -1.f, 1.f),
		FVector(1.f, -1.f, -1.f),
		FVector(-1.f, 1.f, 1.f),
		FVector(-1.f, 1.f, -1.f),
		FVector(-1.f, -1.f, 1.f),
		FVector(-1.f, -1.f, -1.f) };

	//~~~

	//For Each Actor of the Class Filter Type
	for (TActorIterator<AActor> Itr(GetWorld(), ClassFilter); Itr; ++Itr)
	{
		AActor* EachActor = *Itr;

		//Get Actor Bounds				//casting to base class, checked by template in the .h
		const FBox EachActorBounds = EachActor->GetRootComponent()->Bounds.GetBox();

		//Center
		const FVector BoxCenter = EachActorBounds.GetCenter();

		//Extents
		const FVector BoxExtents = EachActorBounds.GetExtent();

		// Build 2D bounding box of actor in screen space
		FBox2D ActorBox2D(ForceInit);
		for (uint8 BoundsPointItr = 0; BoundsPointItr < 8; BoundsPointItr++)
		{
			// Project vert into screen space.
			const FVector ProjectedWorldLocation = Project(BoxCenter + (BoundsPointMapping[BoundsPointItr] * BoxExtents));
			// Add to 2D bounding box
			ActorBox2D += FVector2D(ProjectedWorldLocation.X, ProjectedWorldLocation.Y);
		}

		//Selection Box must fully enclose the Projected Actor Bounds
		if (bActorMustBeFullyEnclosed)
		{
			if (SelectionRectangle.IsInside(ActorBox2D))
			{
				OutActors.Add(EachActor);
			}
		}
		//Partial Intersection with Projected Actor Bounds
		else
		{
			if (SelectionRectangle.Intersect(ActorBox2D))
			{
				OutActors.Add(EachActor);
			}
		}
	}
}

The one time you may run into problems (unwanted extra units being selected) is when they overlap each other from your viewport’s point of view. That would probably require some traces to correct for…