Using weapon optics with different heights, and setting point of impact for certain ranges

What is your guy’s thoughts on a route to take for using various optics along with iron sights (for a FPS shooter). What I mean by that is lets say I have an m4 based rifle with just iron sights. I animate the rifle for things such as idle/ADS/Firing and such in blender for the iron sights and bring it into UE4 and set it up. How i set it up for aiming is with anim montages and I shoot out of the muzzle bone (where the projectile would spawn or line trace depending on what I’m doing). What would be a good way to go about setting it up to work with various optics such as a red dot/holo or magnified optic. With the magnified optic it will be sitting higher than the iron sights were unless I made a super low base for the scope to sit in which would look weird. The red dot/holo would probably be ok as the height would be co-witness with the irons, but I’m not sure how to account for the height of the scope so that its centered in my screen and I’m assuming that creating a separate animation for it with each attachment is not the correct way to tackle this problem. Do i create a camera or something near the stock of the rifle to look through the sights? How I create ADS animations in blender is I have a crosshair X distance away and line the sights up manually to that crosshair so the rifle/pistol will be moved to the camera and I would like to keep it this way as IMO it looks the most natural.

The next question I have is what would you guys do to set the point of impact for the firearm? For example lets say I wanted to be able to zero the rifle at various distances such as 25/100/200 yards, what would be a route to go for that? My first assumption was to get the point in space from the optic/iron sights that goes straight out X distance (lets say 25 yards for now) so that way I have a point in space thats 25 yards infront of the rifles sights. Then use that point in space to calculate the vector (maybe FindLookAt?) to find the direction from the muzzle to that point in space on the vertical (pitch?) axis and fire the projectile so that the projectile starts below the sights and is gradually going up until it intersects the sights (pretending a horizontal line going from your sight picture) at 25 yards and continues to travel above the sights until it comes down and intersects the sights again at X distance (like m193 would intersect again somewhere around the 300-350 yard mark). What route would you guys suggest I take here? Am I on the right track?

hu?
the aim is where the aim is.
First of, if you are attempting to get any accuracy the flight trajectory is a parabola.
You usually do this with Predict Projectile Path

Second. a firearm has ranges at which it is Zeroed in.
In understandable terms this means that the curve you create has 2 “zeros” where the bullet will cross the point you are aiming at. Normally these can be around 50ft and 300ft - for a short weapon anyway. (reading on, you knew this. good).

Your sight is usually adjusted to correct where these 2 spots are. Iron sights get adjusted too.
The barrel is angled upwards, in all weapons (to a fixed degree).

Now, when taking this to UE4 or any game. You basically implement it by following the same principle.
Your sight however on top of the gun it may be can be angled down to correct/adjust the Zero.
Because it’s a game, you can also adjust the rotation of the barrel without anyone being able to actually tell (in real life that’s not possible as you introduce more variables into the equation).

Good Scopes are usually done with a render target camera. and a material that uses the render target. Again, the angle of that camera becomes important in terms of what is being aimed at.

For aiming iron sights, things change.
First you should probably google and learn what a proper sight picture looks like - a lot of people have never bothered actually going to the range it seems. I would say this kind of research is essential when making a shooting game, but it’s obviously not the case is it? :stuck_out_tongue:

Anyway, yes, you place a camera that you toggle on the weapon (as a child actor) and transition the view with blend.
At least for a first person view that isolates the sight picture.
This spot can really be anywhere on the gun mesh.
If you plan on swapping models, save your self some time and create a special socket that every weapon will have where this camera is to be parented at runtime.
This way you can edit the position/rotation at runtime to zero the weapon to a base - and also allow for different possible zeros.

For changing the Zero in a scope. In terms of reality this is never done on the fly. Always at the range beforehand. Which is why you get good a kentucky windnding it when you shoot.
For gameplay purposes, many games allow fort on the fly changes.

The base idea is the same. you cycle through different angles that are pre-set per weapon. You may even want to come up with a standard struct data to use that you pre-assign to each wepaon so that the values can be individualized - they really have to be, as every weapon is bound to have a different angle and distance between the view of the scope and the angle of the barrel.

If you were just learning about firearms, I would suggest making a mok-up where you use the predict projectile path.
Set the values to some realistic values (depending on what you can pull them from bullet information (muzzle velocity, grain, etc). And weapons. You may be able to find accurate assembly info with realistic angles of the barrel.
Don’t worry about the sight angle - just align the sight picture (front bone to rear bone) so that the sight picture is always accurate with minimal sway, and try to do the math to get a result of where the line trace from the angle give off the 2 bones meets the curved path.

More often then not this IS a precise mathematical formula:
for example: Projectile Motion (Physics): Definition, Equations, Problems (w/ Examples) | Sciencing

Last thing:
7 and 1/2 spin is important for instance. I have never seen this implemented in any game. The flight of the bullet is not only parabolic, it’s also elliptical at a known velocity imparted by the muzzle rifling. It would actually be kinda cool to work out a way to impart that.

Thank you for the response, I did a quick skim over everything and will be doing a VERY thorough read tomorrow and thinking about it with what you mentioned tonight. I shoot competitively which is why I’m trying to create something to mimic an experience close to what I get IRL behind the gun. The reason I want to have the ability to zero is for both learning (how to do it programmatically) and if I decide to ever make something that requires it such as a PRS style stage where you generally know the range of the target and your taking it slow(ish) so your better off adjusting for elevation than hold over (obviously depending on the situation) so Id like to replicate that as close as possible in either mils or moa (not sure which yet as I dont do PRS (im a poor) but my friends that do prefer working in mils). Thats another thing to make an attempt to figure out so I guess make a setup to where one click of the turret moves the point of impact up/down a certain distance, but I’m not sure if that would be very gameplay friendly as people would probably say screw it and just hold over unless they could do quick adjustments similar to that of arma with just quick 100/200/300/etc adjustments and that just takes away from the experience.

If you want realistic there are a lot of variables to introduce into the math, including the spin.

The engine is very capable of handling a lot of math at runtime without flinching.

You will however end up running into precision errors because of the nature of the math, so c++ native functions using doubles are probably better then blueprint and floats.

If you shoot competitively, at the very least you know 80% of what I was mentioning which most programmers do not. Its definitely a good start towards realism.

Either way, like in real life, the gun will likely shoot at a constant arc.
​​The sight will be adjusted to correct the sight picture and provide a matematical solution for the bullet arc.
you can solve the spot based on travel speed and the angle of the sight (derived from tip and rear).
Pythagoras ftw, like most things.

well so far did a basic setup for setting up a magnified optic and altering the zero of the rifle for testing (using a free rifle model and scope model so its meh). Created a socket on the scope right in the middle of the glass for the camera to attach to as well as for the zeroing. For the zeroing I made a point in space thats straight out infront of the scope at the zero distance via


FVector ScopeStart = ScopeMesh->GetSocketLocation(FName("s_sight"));
FVector ScopeRot = ScopeMesh->GetSocketRotation(FName("s_sight")).Vector();
FVector ScopeZeroLocation = ScopeStart + ScopeRot * ZeroDistance;

then I found the look at rotation from the muzzle to that point in space and performed a line trace to it to visualize it and they intersect at the zero distance. This works great for a straight line but once it starts to have an arc to it it will have some problems which is where the math that I’m horrible at comes in so thats next. I went with your route of having a rotated barrel instead of trying to rotate the optic to match the barrels impact point which seemed like a HUGE pain to even bother with

Well, it’s the same theory. Rotating the scope and camera means adding either 2 bones or another socket to the rear of the scope so that you can calculate the alignment between the 2 sockets.

either way, the next step would be to use the projectile prediction with the end point at double the distance of the initial 0. I think.

Can you explain what you meant by “the next step would be to use the projectile prediction with the end point at double the distance of the initial 0”? Currently with using projectile prediction i use the start location of the muzzle and for Velocity I take the look at rotation (used for the muzzle to the zero location like 25 yards and such) and multiply it by the velocity of the round in centimetres so 3200fps(roughly xm193 velocity according to my box) converted to centimetres (97536.0f). This is working great but its not working well alongside the zero of the scope which is to be expected. For example if im zeroed at 25 yards and shoot at a target thatss 300 yards away the projectile prediction places it a little overtop of it (which is about right), if i zero at 300 yards and shoot at the 300 yard target the round impacts a few feet below my point of aim. Heres an example with 2 shots aimed at the same location on the target, one zeroed at 25 yards, one at 200, and one at 300 starting from left to right. Point of aim was at the center (vertically) of the cube. Any suggestions on making this work alongside the zero changes?

I was mixing my barrel of monkeys. You don’t need an end location for the projectile prediction path. that’s needed for a straight trace.

What I would do to test the system is put the target out at a fixed distance - disable the movement entirely.
Use a look at node on begin play to line up the shot - eliminating all possible variables.
change the 0 distances with a toggle, and fire the prediction to get the most accurate readings.

It could be that maybe your math has a wrong sign or something similar that is causing the angle (z value of the starting position) to be slightly off from where it should be.
How are you calculating it?
You can’t just get the bone location, as I don’t think it contains the correct Z information.

Also, I need to work a crossbow, so I can give you some more proper examples in the next few days.

heres pretty much my entire setup for testing right now. I’m not using the GetAngle function but thats there to return the angle where the line of the muzzle intercepts with the line from the scope.

code tags messed with the pasting
https://paste.ofcode.org/gQ4rPTVbSEuKjTJXGcMyfs

Am I wrong, or is Start never updated with the angle data?
because you are using start instead of End.
may that be the issue?

Start is just where the muzzle socket is on the weapon, Rot is the rotation to be used to match with the zero (for a straight line) so if the zero is set to 300 yards then you use Start as the starting location for the line and Rot for the rotation of the line and make the length 300 yards and it will intersect with the scope at 300 yards (which is incorrect as its suppose to go above the scope and intersect at 300 yards on its way down). I cannot figure out how to make this setup work right with PredictProjectilePath. I was thinking about connecting several line traces together and attempt to use projectile motion formulas to calculate the trajectory (which is why i made the GetAngle function to get the angle for the impact point but i think i screwed up there as well). Currently as tests I’m using PredictProjectilePath to shoot with so it shoots with the projectile movements path and hits the target, then passes in the amount of time it took to make that hit and then the target plays its hit animation after that time has elapsed so that the projectile that I launch hits the target but the PredictProjectilePath is what actually hits it and does the logic.

Edit: heres an example, shooting at a 300 yard target with a 25 yard zero, then shooting at roughly 1000 yard target (no air resistance as you can tell) with a 25 yard zero https://www.youtube.com/watch?v=_aPppgXrEHs
I’m trying to figure out how to loop line traces together while applying the calculations of projectile motion. I know i would need to loop, I shouldnt need to do it every frame for the projectile (line trace) so a timer could be used in place, but I’m not sure of things like taking in time. I’ve went through these examples here and their starting to make sense (for someone whos never done any physics equations ever and without air resistance) and im struggling to figure out how to apply it to a loop thats making line traces, like the time between the loop how far the projectile should go and the new position that should be applied from the calculation.