The perfect jump: testing techniques for Jumping in Unity3D

In a physics-based engine, there’s many ways to make a character “jump”. For my 7-day FPS entry, I’m trying to work out the perfect jump for my gameplay. Easier said than done. I’m struggling…

Before I go looking for feedback and suggestions, I thought it would help to make a demo showing the things I’ve been trying-out.

Unity webplayer link to try the examples below

Instructions: wait till you land on skyscraper, then hit a number key to select a jump type, and get jumping (spacebar).

Note: if you fall, no problem, it’ll auto-respawn you after a couple of seconds of falling

Option 1: Increase rigidbody.velocity, up

gameObject.rididBody.velocity += new Vector3(0,10,0);

Pros:

  1. Trivial – 1 line of code
  2. Compatible with force-based movement

Cons:

  1. Sometimes doesn’t work with position-based movement (updating position instead of updating rigidbody velocity)
  2. Very little control over what happens (you apply the velocity, but very hard to predict where it lands, or how soon, etc)

Option 2: Increase rigidbody.velocity, forwards

gameObject.rididBody.velocity += new Vector3(0,10,0) + (3.0f * gameObject.transform.forward);

Pros:

  1. Easy – one longer line of code
  2. More realistic: you “leap” in the direction you’re looking. Tilt head up when jumping to jump higher, tilt head more forwards to jump further
  3. WYLIWYL (“willy-will”? “wiley-while”?): Where You Look Is Where You Leap
  4. Allows a variety of jump heights and lengths, with only one button: high obstacles you have to step close to and jump UP; long gaps you have to run towards and jump FORWARDS

Cons:

  1. Not always obvious to the player what’s going to happen (“don’t look down when you jump!”)
  2. Provides a speed-boost forwards, encouraging “bunny-leaping” (like FPS bunny hops, but less stupid)
  3. Much harder for the player to target their landing-position (sideways: slightly hard, distance: very hard)

Option 3: Impulse up (i.e. a one-off Force / Acceleration)

gameObject.rididBody.AddForce( new Vector3(0,10,0), ForceMode.VelocityChange );

// ... or:

gameObject.rididBody.AddForce( new Vector3(0,10 * gameObject.rigidBody.mass,0), ForceMode.Impulse);

Pros:

  1. Easy – one (long) line of code
  2. Slightly more predictable than increasing velocity, maybe – only because you know it’s working in real-world physical units (add a force of (0,9.81,0) to make a character “hover” in mid-air)

Cons:

  1. As far as I can tell, this is identical to increasing the velocity, but uses more typing?
  2. …but requires slightly more code

Option 4: Impulse forwards (i.e. a one-off Force / Acceleration)

gameObject.rididBody.AddForce( 10.0f * gameObject.transform.forward, ForceMode.VelocityChange);

// ... or:

gameObject.rididBody.AddForce( 10.0f * gameObject.transform.forward * gameObject.rigidBody.mass, ForceMode.Impulse);

Cons:

  1. Again, as far as I can tell … identical to setting velocity forwards/up, but requires more code?

Option 5: Constant force (short)


// secondsLeft initially to 0.5

void FixedUpdate()
{
   while( secondsLeft > 0 )
   {
      secondsLeft -= Time.deltaTime;
      player.gameObject.rigidBody.AddForce( new Vector(0,10,0), ForceMode.Acceleration );

// OR: ...

      player.gameObject.rigidBody.AddForce( new Vector(0,10 * player.gameObject.rigidBody.mass,0), ForceMode.Force );
   }
}

Pros:

  1. Player can target the landing-point better
  2. Feels like a jetpack (it IS a jetpack! just an invisible one)
  3. Slow take off, but long hang-time

Cons:

Option 6: Constant force (long)


// secondsLeft initially to 2.0, force is reduced to make up

void FixedUpdate()
{
   while( secondsLeft > 0 )
   {
      secondsLeft -= Time.deltaTime;
      player.gameObject.rigidBody.AddForce( new Vector(0,7,0), ForceMode.Acceleration );

// OR: ...

      player.gameObject.rigidBody.AddForce( new Vector(0,7 * player.gameObject.rigidBody.mass,0), ForceMode.Force );
   }
}

Pros:

  1. Player can target the landing-point better
  2. Feels like a jetpack (it IS a jetpack! just an invisible one)
  3. Even more floaty / long hangtime than previous option

Cons:

Option 7: Impulse up AND forwards

gameObject.rididBody.AddForce( 10.0f * gameObject.transform.forward + new Vector3(0,4,0), ForceMode.VelocityChange);

Pros:

  1. Unlike Impulse-forwards, you can jump up without always glancing at the sky first
  2. Inherits the “height control” aspect of Impulse Forwards

Cons:

    Bunny-leaping is even easier – just point forwards and keep spamming the space-bar

Option A: Trajectory arc

(not implemented yet)

Pros:

  1. Player can precisely target the landing-point
  2. Precisely re-windable, pausable, speed-up/slow-down (bullet time) – (because it’s parametric)

Cons:

  1. No mid-air steering for players
  2. Code is much more complex: requires a whole GUI/HUD system for targetting, on top of the calculations for the jump
  3. Code is highly dependent on other code: any “external” force or collision that happens while in-air has to be dealt with as special case

Option B: The FPS Controller

(not implemented yet)

Pros:

  1. Built-in to Unity
  2. Less debugging

Cons:

  1. Lots of code, quite complex, not easy to customize
  2. Only has one model of jumping – works, but depending on your game might be unrealistic and not fun

4 thoughts on “The perfect jump: testing techniques for Jumping in Unity3D

  1. Keith 'DeadlyDad' Olson

    One option that I haven’t seen done yet is to cast a ray forward, then drop a marker there, green if it is within jumping range, red if it isn’t. If the player jumps while it is green, code the jump to land there.

  2. adam Post author

    One of my builds I did something similar – I drew the parabolic arc / path of the jump, in 3D, as a HUD. It simulated forwards in time, calculated all positions, and drew them in a single mesh.

    But Unity dynamic mesh rendering is/was AMAZINGLY slow – like: 100x slower than it should be (obviously not hardware accelerated), and I didn’t have time to work out what magic you need to do to the Unity API calls to make it work correctly.

Leave a Reply

Your email address will not be published. Required fields are marked *