Barrel aim Reference reticle, same as in Warthunder/WoT

When playing Warthunder, there are 2 reticles on the screen, one where the mouse is aiming, and the other that shows where the tank barrel is actually pointed.

I want to add this barrel reference to my game but I cant seem to find much in the way of help (translation: google failed me)

I’m thinking that i need to do a trace, and reference a UI element to that.

Can someone point me in the right direction?

How accurate do you want the secondary crosshair to be? Do you want it pointing in the general direction, pointing at the end of a line trace, or pointing at the hit location of a projectile? Pointing in the general direction is fairly easy.

Doing a line trace version you have to think about empty trace results and where the crosshair would be positioned then.

Going on the actual hit location would require calculating the projectile trajectory.

That being said the relevant function is ProjectWorldLocationToScreen in C++. There is a bug however that makes this a bit of a mess when dealing with the UI blueprint.

Far Too Long Explanation Of The Bug

That was back in version 4.6 and now on 4.23 it still isn’t fixed.

I’m thinking just a general indicator, not terribly accurate.

I will have a look.


I got something working without too much trouble using widget anchor points instead of widget transforms. If you notice, though, the two crosshairs do not line up evenly and this will be more work and fidgeting. Anchor points use floats between 0 and 1 and precision is a problem.

Crosshair Example

I will post how I did it sometime today.

1 Like

Oh, That is perfect!
I just wanted to make it easier for the player to know the rotation limits of the barrel.

Step 1: Since we have an AimingComponent reference in the UI blueprint already storing the secondary crosshair location there works well. So add this to TankAimingComponent.h

		FVector2D SecondaryCrosshairLocation;

Step 2: The screen/world stuff is done in TankPlayerController.cpp so wherever you have the DeprojectScreenPositionToWorld (or maybe you went for the alternative GetHitResultAtScreenPosition) you can add this.

barrel = however you reference your barrel in tankplayercontroller and socket names should be yours

       FVector firingLocation = barrel->GetSocketLocation("FiringLocation");
       FVector endLocation = firingLocation + (barrel->GetForwardVector() * 5000.f);


The above line is where the world position is determined.  This endLocation (straight ahead of the barrel in this case) can be replaced by line tracing or calculating the projectile path.

	FVector2D ScreenLocation;
	ProjectWorldLocationToScreen(endLocation, ScreenLocation);
	int32 viewSizeX, viewSizeY;
	GetViewportSize(viewSizeX, viewSizeY);
	float adjustedX =  ScreenLocation.X / viewSizeX;
	float adjustedY = ScreenLocation.Y/ viewSizeY;


Since we are going to be using anchor points which are a percentage of the UI Canvas the bug of UMG thinking all canvases are 1920x1080 is no longer relevant.  The screen location is divided by the screen size which gives the necessary floats in a value from 0 to 1 which is how the UI widget anchor points are implemented.


	FVector2D adjustedScreenLocation = FVector2D(adjustedX, adjustedY);
       AimingComponent->SecondaryCrosshairLocation = adjustedScreenLocation;

The changing of the crosshairs as I have done goes a bit deeper in to referencing separate Enums. I will show the blueprint setup in a bit.

In the Player UI blueprint put a new Image widget down for the second crosshair. It does not matter where because it will change programmatically. Zoom in close on the new image (shown here as one of my crosshair pngs) and move the anchor to this position. For a reason I can’t figure out yet directly centering the anchor to the middle of the image will have an offset in game. Setting the anchor to the same ratio used before (50%/33%) for the original crosshair but INSIDE this image seems to get the closest for both crosshairs to line up.

editor%201 .

Now go to the Graph that was used to bind the original crosshair color. This is what mine looks like now (although I would do a separate binding for each crosshair I put this all in one to simplify what is going on.)

I created an array variable of type SlateBrush called CrosshairPool that has all the different pngs that could be used. The AimingReference node has a variable now SecondaryCrosshairLocation which is a FVector2D of the 0 to 1 floats. The relevant point here is to pull a SecondaryCrosshair node on to the graph. Pull out a pin and Get SecondaryCrosshairLocation from the AimingReference. Feed the output in to BOTH minimum and maximum anchor points of a Set Anchors node. Set Anchors is arrived at through the SecondaryCrosshair image node-> a Slot To Canvas Slot node (to cast up to something that actually has anchors) and then Set Anchors. All done. The rest is just adding the complexity of calling AimingReference blueprint callable functions dealing with aim states then setting the SlateBrush of the Image widget.

Privacy & Terms