Hi,
The goal is to paint the flight path before the player launches the projectile.
My first idea was to use Unity itself to draw the path for me so I don’t have to mess with the formula but I have not found any API for doing that. If there is any I have overlooked, please help me out here.
So I started looking and I have found many posts here and all over the internet. I tried different equations and code I found and finally wrote my own implementation but I never got the result Unity does. One reason for my own formula was that the others I found didn’t include mass and drag where I could remove mass (I think) but not drag.
The flight path is drawn properly, input and control feels kinda good, but when you actually launch the projectile it either flies a tiny bit too far (mostly) or not far enough.
So I am pretty close and have no idea why I can’t have nearly exact same results.
To be precise the algorithm takes the rigidbodys properties (velocity, mass, center of mass and drag) and the gravity vector into account.
public void SimulatePath(GameObject gameObject, Vector3 forceDirection, float mass, float drag)
{
Rigidbody rigidbody = gameObject.GetComponent<Rigidbody>();
//float timestep = Time.fixedDeltaTime / Physics.defaultSolverIterations * stepSize;
float timestep = Time.fixedDeltaTime * stepSize;
//float timestep = stepSize;
float stepDrag = 1 - drag * timestep;
Vector3 velocity = forceDirection / mass * timestep;
Vector3 gravity = Physics.gravity * stepDrag * timestep;
Vector3 position = gameObject.transform.position + rigidbody.centerOfMass;
Vector3[] segments = new Vector3[maxSegmentCount];
int numSegments = 0;
segments[0] = position;
numSegments++;
for (int i = 1; i < maxSegmentCount && position.y > 0f; i++)
{
velocity *= stepDrag;
//position += velocity * 1.28f; // ????? - This came pretty close at one configuration
position += velocity;
position += gravity;
segments[i] = position;
numSegments++;
}
Draw(gameObject.transform, segments, numSegments);
}
I pass mass and drag as parameter because they might be affected before I then launch the projectile but will be set before launch. The simulation values and the launch values match.
maxSegmentCount can be set in the editor as well as stepSize.
The Draw(…) call will then set up the line renderer.
Disclaimer: The code has changed over time but this is the current version with the best results. There are things about this formula which I am not sure about and which I would think of being different.
For example messing with the timesteps makes often things go worse. I’d assume changing the timestep should not change the drawn path except for it to become more bumpy or more smooth.
I have a headache looking at how I use gravity. I found approaches having timestep ^ 2 which could make sense but the value gets too small for a float and ends up being 0.0000xx and the path looks like shooting linear into the sky. In my code the gravity is linear. I think that gravity is a constant force over time where the loop takes care of the time. What I did not try is instead of timestep ^ 2 using elapsedTime ^ 2 or have a gravitational velocity which would make more sense right now.
Gravity is also affected by drag as you can see in my code so I apply constant gravity with drag but velocity decreases over time.
Update while writing the post: I wanted to try the gravitational velocity:
Vector3 gravitationalVelocity = new Vector3(0f, 0f, 0f);
Vector3 gravity = Physics.gravity * stepDrag * timestep * timestep;
for (int i = 1; i < maxSegmentCount && position.y > 0f; i++)
{
gravitationalVelocity += gravity;
position += gravitationalVelocity;
}
But same thing here.
It made so much sense writing the initial formula but the more I look at that the more I would try change.
It took me hours so far searching for problems and at the moment I am kinda blind right now. I cant see straight and started to just try around because of despair and need some help.
Thank you so much for opening my eyes.