An introduction to character physics

A physics character is a collision object used to simulate game characters (people) walking, jumping, and falling.

The standard physics character makes some simplifying assumptions:

  • The character’s shape must be convex.

  • The character remains upright even when jumping or falling: no sitting, squatting, ducking, or lying down.

  • Limits are placed on:

    • how steep a slope the character can climb,

    • how high a step the character can climb, and

    • how fast the character can fall.

Like a dynamic rigid body, a physics character has a collision shape, a location, and a gravity vector, along with velocities and damping parameters. It also has an option for contact response, which is enabled by default.

However, a physics character has no concept of mass, and its motion is controlled very differently from a dynamic body. Instead of applying forces or directly updating the character’s velocities, the app should specify when and how the character should walk and jump.

Direct creation

You can create a character by directly invoking the PhysicsCharacter constructor. This allows you to specify its collision shape and step height.

HelloCharacter is a simple application that demonstrates the direct creation of a character, followed by automated jumps. Things to notice about the app:

  1. The constructor requires a convex shape. In this app, a capsule is used.

  2. By themselves, the character and the ground are both invisible, so the app uses debug visualization to reveal what is occurring in physics space.

  3. The onGround() method tests whether the character is supported by a solid surface (as opposed to jumping or falling).

Since directly created characters don’t look like much, even in debug visualization, they are mostly used to represent players in single-player games with a first-person viewpoint.

CharacterControl

To associate a character with a spatial, there’s a CharacterControl class that implements the PhysicsControl interface.

For a CharacterControl, the physics control and its collision object are not the same object! In fact, no collision object is created until the control is added to a spatial.

To access the collision object associated with a control, use characterControl.getCharacter(). To access the control associated with a collision object, use:

(CharacterControl) character.getUserObject();

HelloCharacterControl is a simple application that demonstrates the creation of a CharacterControl.

Things to notice about the app:

  1. The character’s collision shape is a capsule.

  2. The center of the Jaime model is located between its feet. If the control were directly attached to the model, its capsule shape would be off-center. In order to match the model to the physics, the control is attached instead to a centerNode located near Jaime’s chest.

  3. Because control provides convenience methods such as onGround() and jump(), the app never accesses the collision object directly.

Walking

A character’s walking motion is controlled by its walk direction vector. During each simulation step, the horizontal component of the walk direction gets added to the character’s location. To stop the character from walking, invoke setWalkDirection(Vector3f.ZERO).

Despite its name, the walk direction need not be a unit vector.

HelloWalk demonstrates keyboard-controlled motion of a physics character. Things to notice while running the app:

  1. Move the mouse to turn the camera.

  2. Because the app uses a first-person viewpoint, the character is invisible. Nonetheless, the character’s shadow can be seen. Find it!

  3. Press Space bar to jump.

  4. Press W to walk in the camera’s forward direction.

  5. Some of the mountains have slopes too steep for the character to climb.

For an example using a third-person viewpoint, see HelloWalkOtoCc.

  1. Press Space bar to jump.

  2. Press U to walk in the camera’s forward direction.

  3. Press H to walk to the camera’s left.

  4. Press J to walk in the direction opposite from the camera’s forward direction.

  5. Press K to walk to the camera’s right.

Configuration

The configuration parameters described in this section apply to both PhysicsCharacter and CharacterControl. The control provides convenience methods to get/set some of these parameters. The rest may be accessed by way of characterControl.getCharacter().

Gravity and up direction

The up direction of a physics character is a unit vector that points in the direction opposite its gravity vector. By default, the up direction is (0,1,0) and the gravity vector is (0,-29.4,0).

A character’s default gravity is 3x stronger than the default gravity of a PhysicsSpace.
Unlike the gravity of a rigid body, a character’s gravity is never overridden by any physics space.

To alter a character’s gravity vector, use character.setGravity(Vector3f).

Altering the gravity vector automatically updates the character’s up direction. To alter the magnitude of a character’s gravity (without changing its direction) use character.setGravity(float).

To alter a character’s up direction, use character.setUp(Vector3f). Altering the up direction automatically updates the gravity vector.

Jump speed

If a character jumps in its up direction, its predicted rise time and jump height are determined by its gravity and jump speed. Roughly speaking:

float g = character.getGravity(null).length();
float v0 = character.getJumpSpeed();
float riseSeconds = v0 / g;
float jumpHeight = v0 * v0 / (2f * g);

The default jump speed is 10 psu per second. To alter a character’s jump speed, use character.setJumpSpeed(float).

Fall speed

Fall speed limits the speed of a falling character. To be realistic, it should be larger than the character’s jump speed.

The default fall speed is 55 psu per second. To alter a character’s fall speed, use character.setFallSpeed(float).

Step height

Step height limits how high a step the character can climb. To be realistic, it should be less than the character’s height.

A character’s initial step height is set by the constructor. To alter it, use character.setStepHeight(float).

Maximum slope

Maximum slope limits how steep a slope the character can climb. It is expressed as an angle in radians relative to the horizontal plane.

The default maximum slope is π/4, indicating a 45-degree angle. To alter it, use character.setMaxSlope(float).

Contact response

As with a rigid body, you can disable the contact response of a character using character.setContactResponse(false).

Disabling a character’s contact response will compel it to fall, at least until contact response is re-enabled.

BetterCharacterControl

Many limitations of PhysicsCharacter and CharacterControl are hardcoded into Bullet. To work around these limitations, you may wish to implement your own physics controls for characters.

BetterCharacterControl (BCC) is a custom character control that implements ducking and look direction. You can use it as a model for implementing your own physics controls.

BCC is based on PhysicsRigidBody, not PhysicsCharacter.

There are many differences between BCC and CharacterControl. For example:

  1. The collision objects are located differently. BCC locates the collision object near the character’s feet, whereas CharacterControl centers it where a person’s hips would be.

  2. The APIs to instantly relocate the character are different. BCC provides a warp() method, whereas CharacterControl allows you to invoke setPhysicsLocation() directly.

  3. The setWalkDirection() methods have different semantics. In BCC, the argument is a velocity vector (psu per second), whereas in CharacterControl the argument is a displacement (psu per simulation step).

  4. The APIs to test whether the character has physical support are different. BCC has isOnGround(), whereas CharacterControl calls it onGround().

  5. A CharacterControl will pass right through another CharacterControl without colliding, whereas a BCC can detect collisions with other characters.

  6. A BCC has mass and can be configured for kinematic motion, whereas a CharacterControl has no mass and cannot be made kinematic.

  7. BCC is more customizable than CharacterControl.

HelloWalkOtoBcc is a simple application that demonstrates walking and jumping with BCC and a third-person viewpoint. The user interface is identical to HelloWalkOtoCc:

  1. Press Space bar to jump.

  2. Press U to walk in the camera’s forward direction.

  3. Press H, J, or K to walk in other directions.

The Jme3Examples subproject contains several demo apps that showcase physics characters.

  • The TestQ3 demo app demonstrates a first-person walkthrough of a fictitious ancient temple. It uses a directly created PhysicsCharacter.

  • The TestPhysicsCharacter and TestWalkingChar demo apps use CharacterControl and a third-person viewpoint.

    • TestWalkingCharacter demonstrates the Oto model walking and shooting, with appropriate skeleton animations.

    • TestPhysicsCharacter demonstrates the Sinbad model walking and jumping, but doesn’t use skeleton animations.

  • The TestBetterCharacter demo app demonstrates the Jaime model walking, jumping, and ducking. It uses BCC and a third-person viewpoint.

Summary

  • A physics character simulates a game character walking, jumping, and falling.

  • To associate a character with a spatial, use a CharacterControl.

  • For CharacterControl, the physics control and its collision object are not the same object!

  • If the built-in character controls don’t meet your needs, you can implement your own.