Sure! Finding stuff like this is usually pretty straight-forward once you know what to look for.
The most important thing when you’re debugging something is generally the ability to work backwards. You already know you’re getting the wrong result, so you start at where that result is shown and slowly try to see where that result comes from.
You essentially already did a decent chunk of the work for me by pointing out the problem likely lies within the Parabola:setDomain()
method in your original post, so the first thing I did was find that module and read through it. With that philosophy of working backwards, I looked for the code responsible for actually calculating a point on the parabola, since that’s likely where I’ll start running into the problematic code. I found the Parabola:samplePoint()
method, and I can see from the line y = (a * x * x) + (b * x) + c)
(the general equation for a parabola is y = a * x^2 + b * x + c
) that I’m on the right track.
I actually originally suspected that the problem was with the scaling of the t
parameter, and that the domain would be set once and then never changed. But I couldn’t be sure of that, so I decided to check where Parabola:samplePoint()
is actually called. In Studio, the fastest way to do that is usually to press Ctrl + Shift + F and search some text across all scripts. I searched for :samplePoint
:
There’s a few results within the Parabola module, but those are all inside methods that seem to have dedicated purposes such as rendering a beam, finding what parts the parabola collides with, and so on, so I decided to check out the one result that was in the BulletWeapon module. That leads me to here:
And this immediately points out to me that I was wrong about my original assumptions: samplePoint()
is only ever called with an argument of 1, and the domain slides along the parabola to determine where the projectile currently is along its path. Since samplePoint
is only ever called with an argument of 1, that also means that the point is always sampled at parabola.x1
- we see that on this line: local x = x0 + (t * (x1 - x0))
.
How we know this
That line calculates x
as x0
plus the difference between x1
and x0
. We can simplify that down:
x = x0 + (1 * (x1 - x0)) = x0 + x1 - x0
At which point the two terms of x0
cancel out and we’re left with just x1
.
By extension, that means that the point is always sampled at projFront
, so we work backwards to see where that value comes from. In this case, I’ve often found it helpful to highlight the variable’s name and just scroll through the code to see where else it comes up. By scrolling up, I found this:
And by repeating the same process, I found that pTravelDistance
is set here:
I then do the same for bulletSpeed
and find it’s set here:
Because it always comes from the same configuration value, I know that the value of pTravelDistance
, and by extension, projFront
always increase at the same rate regardless of the angle you fire at. This makes steeper trajectories increase the bullet velocity tremendously, because for the same distance travelled horizontally it covers a lot more distance vertically.
So, of course, now we know what the problem is and where the code that’s causing it is located. The next issue is solving it. Since that function clearly contains the bullet simulation code (or, well, in this case, rocket simulation code ), the direction the rocket in has to be passed in somewhere. And I didn’t have to look far:
In this case, I’m expecting fireInfo.dir
to be a “unit vector”, i.e. a Vector3 that always has a magnitude of 1. Assuming that’s true, we can just get its horizontal length and multiply bulletSpeed
by that value to scale it down when you’re firing at a steep angle.
In 3D space, the length of a vector is calculated as:
Because y
will always be 0 (we’re only interested in X and Z), we can simplify that out. And that’s how we got the solution I suggested in my first post.
Hopefully this helps!