Third Person Shooter - Aiming at Crosshair

(This all may seem obvious to anyone having worked on this before but this is my first time encountering it and it took me a little bit to work through the issues.)

The premise is pretty straightforward: With a third person shooter, how can I ensure that projectiles coming from the character will have the expected trajectory when the actual aiming is done with a crosshair?

I have a crosshair drawn in the middle of my HUD, in the center of the screen. It indicates the center of the camera for the character. My camera is above and behind my character (to the right) so that I can see the character clearly.

https://i.imgur.com/6eeo04Y.png (Crude MSPaint representations drawn from above to better show the issue I’m facing)

When I want to fire a projectile, I do a Line Trace by Channel from the camera’s location (center of the crosshair) to a point 5000 units away (using the camera’s “forward” vector). This gives me the location of either a colliding object or the location of the end of the trace.

I use the above location and the character’s world location in a Find Look At Rotation to find the correct rotation of the projectile and spawn it at the character’s location.

The end result is that projectiles fired from the character will hit the point where your crosshair is pointing. This is good and works well as long as you are accurate with your crosshair.

So let me describe a scenario. You’re shooting at an enemy, headshot headshot headshot because you’re a pro. But then your cat bumps your arm and your crosshair is slightly off - just to the left of the player’s head. But instead of the projectile whizzing by their ear, it ends up being several feet to the left. The reason for this is that the initial line trace went out 5000 units, way beyond the target and hit open air. The projectile is then launched towards that far-away point and the trajectory makes it miss the player by a LONG shot rather than barely missing.

In a similar scenario: You’re shooting at an enemy but you’re terrible because you just found out your cat’s on fire and it’s bothering you. You’re firing over and over at a stationary enemy but you can’t aim right and your crosshair is a good deal to the right of the player. Despite this, you are landing shots on the player every time. Since the line trace from the camera went beyond the target, the impact location ended up behind the target so the projectile is launched toward it and manages to hit the target anyway.

Effectively, what is seen here is the same as if you were to hold a gun in your right hand, hold it way out to the side and fire it where you’re looking. Don’t think about the logistics of trying to comfortably hold a gun that way - that’s not the point.

The takeaway is this: The greater the distance between the camera location and the firing location, the greater the error will be when firing. I have compensated for this a bit by adjusting the projectile’s rotation but this only works if the crosshair is pointing exactly at where you want to hit. Otherwise, it becomes a mess. As far as I know, there is no way to fix this problem keeping the current setup. There is no way to simply know what it is you meant to be aiming at and this implementation will always feel clunky. If you disagree, I would be happy to learn a new way to deal with this.

So - what else can be done? That’s what I’ve come here to ask. So far, my only idea is to reduce the distance between the camera and the player.

I have seen games where, when you are aiming, the camera is effectively “zoomed in” to be above the gun, either so you’re looking down the sights like you would in a first person shooter or close enough that it doesn’t make a difference - possibly all you’d see is a part of the character’s head/shoulder and the gun. However this method doesn’t look good for all styles of games and, depending on the gameplay, constantly zooming in and out will get jarring.

It is also possible to just try to keep the character and camera closer by default. At the moment, my projectiles are firing from the center of the character which looks weird and isn’t permanent but it’s a basic implementation. If I add a firing animation where the character holds up their weapon to their right shoulder, the distance between the camera and firing location is reduced a good amount. Likewise, I can probably squeeze the camera in a little more without TOO much negative impact. But I don’t want the camera to be so close that you can’t see your character anymore and I don’t want most of your screen to just show the back side of your character. So getting this balance will be tricky. Overall, this will reduce the error but will not fix it consistently. It will always make sense to aim to the right side of things because, if you miss with your aiming, your projectile might still hit.

Another solution would be to have a targeting system so you’re not relying on being accurate with the crosshair but this reduces some of the “skill” needed to be accurate.

I’m certain others have encountered and dealt with this scenario. I am trying to find other third person shooter games where I can test how it works there as well. Does anyone have any good examples? Suggestions? Thoughts? It kinda feels like most of the questions/discussions I post here go unanswered so I’m not truly expecting a response … but I’m still hopeful.

Thanks for reading

Edit: I did some searching (through Google instead of directly in the forums) and found a lot of people referencing “aim offset”. I found some tutorials on it and will go through tonight to see if that helps … sounds like what I need so I’m hopeful.

Edit2: Oh, this isn’t actually addressing what I’m talking about, this is just making the character face the correct direction which I will also need but it doesn’t resolve the issue I’m seeing above. On this page, the animation process is described: Creating an Aim Offset | Unreal Engine Documentation but ultimately this works because the camera is already behind the gun.

Hi, you could do a linetrace from the weapon first, distance say 2000, then use the hit result to switch between the two transforms or do some other tweaking.

I’m not completely following you. If I do a line trace from the weapon, the location will be very “off” from the crosshair. The character needs to be rotated to face the crosshair location… Without that the line trace from the weapon/character is largely meaningless.

But I’m also not sure how this is “normally” done so maybe I’m missing a major point here.

I just do a line trace from the tip of the weapon bp. I add a sphere or socket as the starting location to the tip of the weapon and then use the line trace by channel node. The starting point is the sphere location. the end point is the sphere location + a value that essentially equals the range of the trace. To do the aim over the shoulder I create an input button in the project settings to aim and when pressed I use a timeline and change the field of view of the camera. When the button is released I just play the timeline in reverse. So smooth and on point.

I started going in this direction. I did a line trace from the weapon and took the hit result, converted it to screen coordinates relative to the player’s viewport and drew a crosshair on the HUD at that location instead of the exact center where I had it. But this still wasn’t the MOST accurate.

The problem is if your camera is facing something you should hit, it’s possible that your gun, facing in that direction, would shoot behind the target.

To resolve this, I took the hit result from the gun’s line trace and performed a second line trace from the camera location to the gun’s hit result. If it found something between the camera and the gun’s hit result, use the new hit result instead.

The result is not bad. The crosshair does “float” around a bit as it now moves around the screen. It functions more like a laser sight now instead of a crosshair. But I think it will work.

A bit late, but I was thinking of this and found the answer right after stumbling here.
Sorry for necro, I hope this may help any poor soul in the future.

The problems are:

  1. Tracing from the gun’s location to the camera’s forward doesnt work because sometimes it doesnt hit where it should (some weird offset). This becomes more apparent the further away the camera is from the gun on the X axis.

  2. Tracing from the camera location to the camera’s forward also doesnt work because the camera may be too far ‘behind’ the player and may be intercepted by something in between.

The solution:
What we need to do is “project our camera’s position onto our gun”. Like merging both positions.
Our trace ends up looking like this:

include “Kismet/KismetMathLibrary.h”

traceStartLocation = UKismetMathLibrary::ProjectPointOnToPlane(camera->GetCameraLocation(), GunLocation, camera->GetActorForwardVector());
traceEndLocation = traceStartLocation + (camera->GetActorForwardVector() * Range);
do the trace.
If it something, to be really sure nothing else is in the way; then trace from the GunLocation to the TraceHitLocation.

Precisions:
My aiming crossair is at the middle of the screen.
My Character, gun and Camera are set as in the image.

2 Likes

There is nothing unexpected about this. Perhaps you want to implement aim assistance.

So, here’s how I approach it.
First trace the channel setting end to the center of screen and beginning to the position of camera. This will help us actually get the point where the crosshairs are intended to hit.
Second, draw the channel again, but this time the beginning will be your rifle(or any other weapon/spot) and the end will be the point given by the previous channel. This way, the distance of the target is updated in real time and shots are accurate.
Here’s a breakdown using illustrations:
This illustration is just to restate the problem we all are here for…


Now, as per our implementation, we first take inputs from the camera channel before aiming the gun…

With the insights from the camera angle, we can now aim our gun to accurately and precisely shoot at the crosshairs, regardless of distance…

Here’s the implementation for those who’d like to see stuff in action…

{This grab is taken raw from my project, so it contains logic to make the aim imprecise on purpose by using random. But you can still get a good idea}.
Peace