- Home /
What is the best way to map the curve of a jump?
Ok so the question is simple. If you know the jump force, you know the gravity, and you know the velocity, can you map out the curve of a jump?
This is for a really simple patrolling/jumping AI critter... Very simply put, he walks back and forth, and uses a simple raycast to see if there is ground in front of him. If there isn't, flip and reverse direction. SIMPLE and awesome! Weeeee!
Now the kicker, I want to make him jump from platform to platform. I've done this pretty easily by treating him like any other moving character. Setup a speed multiplier, assign a jump force (using Impulse, FYI), etc etc.
So I "map" out my possible jump like this:
If there is no ground in front of him (normally would just flip) I draw a ray up to what I calculate to be the Apex of the jump, then back down identically to the other side. If the second ray detects ground, JUMP (you have something to land on!). However, I am just using 2 straight lines, and it doesn't seem to be too accurate.
I'm hoping someone has a reasonably simple way to graph out the jump, using Debug.linecast (or something visual in the scene view) so that based on the current velocity/gravity magnitude/jump force (again IMPULSE, I"m not even sure how Force works now that I've been trying impulse) you can see the curve of what the jump will be. Should be easy since we have basically all the variables, I'm just not sure of the formula. Here is what I have so far:
//The gravity magnitude
float grav = Physics2D.gravity.magnitude;
//our current velocity. Since there is no resistance, character should be able to move through the AIR at the same rate as on the ground right?
//So airborn velocity shoudl be the same as grounded velocity
jumpCheckDistance = Mathf.Abs(m_Rigidbody2D.velocity.x);
//How high can he jump? Basic formula (I think) of: Force squared * (gravity *2)
float jumpHeight = jumpForce * jumpForce / (2 * grav);
//Now set the points. jumpCheck (Vector3) shoudl be the APEX of the jump...
//NOTE: currentSpeed is the velocity, we simply multipy it by -1 if < 0 since we will be going the OPPOSITE way (flips the direction of the raycast)
//Also NOTE: foot is an empty game object i place at the bottom of the character to measure from the ground (for grounding and what not).
jumpCheck = foot.transform.position + (new Vector3 ((jumpCheckDistance/2) * (currentSpeed > 0 ? 1 : -1), jumpHeight));
//jumpCheckGround is the position of where he shoudl land based on the jump. Basically an identical line as the last, drawn from the apex down... the second half of the "bell curve"...
jumpCheckGround = jumpCheck + new Vector3 ((jumpCheckDistance/2) * (currentSpeed > 0 ? 1 : -1), (jumpHeight) * -1);
So this creates a fairly accurate representation of the jump, but it's not totally accurate. Is there anyway to get this closer? Or rather, can anyone show me a formula to calculate the true apex of the jump, and the position of the landing (or really, I woudl like the whole curve, so I can tell where he will collide, etc)?
Let me know if this isn't very clear, I'm a little rushed this morning. Thanks everyone!
Adam
Answer by AlwaysSunny · Apr 20, 2015 at 11:43 AM
If you have sufficient knowns (you do) you can discover your unknowns.
Have a look at the "big four" kinematic equations.
You'll need to run the equation several times in a loop with different TIME values to build a prediction. The more iterations (with smaller time steps) the greater the fidelity of the prediction. Each discovered displacement will be a point in the parabola you are creating.
Your goal is the DISPLACEMENT, so methinks
d = (v' * t) + (1/2)(a)(t^2)
is the formula you need. Your ACCELERATION is Physics.gravity. The INITIAL VELOCITY is going to be the velocity your object would have if he jumped during that frame. This can be worked out by knowing the direction and magnitude of the force vector you would apply and the object's mass.
At each iteration, you may want to also know the FINAL VELOCITY, which would give you the direction of the ray you'd cast to check for a valid landing. There's a formula for that there too. Note this step is somewhat optional. A raycast "down" should be sufficient, perhaps with a "suggestion" of the jump's X direction for added insurance.
This approach will not help you discover any obstacles in the path; for that, you'd have to ray- or sphere-cast along each segment of the parabola. For anything more sophisticated like prediction of reactions to obstacles, you'd need a recursive function that tests for obstacles with each iteration.
This is great, I'll get to work on this in a few. However, with TI$$anonymous$$E, would that be delta time, or a representation of the total time of the jump?
Any chance I could get you to write out a quick loop that would help explain how to best calculate this and display it in Scene view?
I really appreciate your help so far! Thank you again
No problem, it's not often I get to stretch these mental muscles. Which also means I'm pretty rusty with this stuff, so this is a bit of guesswork:
// getting the initial velocity
initialVelocity = body.velocity + jumpForceVector.normalized * (jumpForceVector.magnitude / body.mass);
// the loop, returns array of sequential points
// representing a parabola of the projected trajectory
Vector3[] Trajectory(int steps, float timeStep, Vector3 initial) {
Vector3[] traj = new Vector3[steps];
for (int i = 0; i < steps; i++) {
float t = timeStep*i;
traj[i] = initial * t;
traj[i] += 0.5f * Physics.gravity * (t*t);
}
return traj;
}
If I've made a mistake here, hopefully you'll spot it. This should get you in the ballpark, anyway. You could optionally rewrite this to include the raycast check for a valid landing spot. This way though, it's re-usable for other situations.
Just loop over the returned array, raycasting between the current and next point (optionally drawing these rays with Debug.DrawLine() so you can visualize the trajectory yourself). If you hit something, it's either an obstacle or a valid landing zone. The normal of the first detected hit, if any, should give you a good idea of which is the case. No hit either means the steps are too few, the timestep is too small, or the jump may be into the unknown abyss...
Hope it's helpful, :)
This is awesome. I'm starting to get the feel for what i need to do. One last question. Sorry to be so daft here today, but what would steps and timestep be? Are we refering to the TimeStep in the Time settings for the project? Again, sorry to be such a pest on this one, but you definately have given me a GREAT deal of help so far! thanks again!
The "big four" kinematic equations are used to predict the future position or velocity of an object experiencing a constant acceleration.
Time in the equation is the number of seconds in the future you are predicting. So you run the equation many times to ask, what would the displacement be after (t) seconds. After (t*2) seconds, after (t*3) seconds, etc. This builds a trajectory prediction.
In this formula, the "time" variable has nothing to do with Unity's time, deltaTime, time settings, or any of that. It's just saying "where would the object be after TI$$anonymous$$E seconds".
In a much simpler scenario, if you did not want to check for obstacles or draw the parabola, it would be sufficient to run the equation once with a big "time" value, to predict the "final" position.
So how many times you should run the equation (steps), and the (timestep), should be found experimentally based on how far into the future you want to predict. I would think 10-25 steps would be reasonable, and the timestep should be something like 0.2 or 0.3 seconds.
Very glad to be of assistance. Classical Physics was the closest thing to "fun" I took in college, despite the homework taking 8-12 hours a week. Fascinating stuff, and definitely useful in game design.
Your answer
Follow this Question
Related Questions
My jump script doesn't work every time 3 Answers
The faster it goes, the longer it jumps 1 Answer
gravity doesnt seem to effect my first person controller....help! 1 Answer
The faster my character goes the longer he jumps. 1 Answer
Edit this script so that on the second jump change the gravity to 5 2 Answers