Skip to main content

Rigid Bodies

A rigid body is an entity that takes part in the physics simulation. It needs two components: a rigidbody component, which decides how the physics engine treats the entity, and a collision component, which gives it a shape. A rigidbody component without a collision component has nothing to collide with and does nothing. Shapes are covered on the Collision Shapes page; this page is about the body itself.

Body Types​

The type of a rigid body decides who moves it:

  • Static - Never moves. Use it for the ground, walls and anything else that is part of the environment. Static bodies are cheap because the engine assumes they stay put: it places them when they are created and never checks their entity again.
  • Dynamic - Fully simulated. It falls under gravity, responds to collisions, forces and impulses, and the physics engine owns its position and rotation.
  • Kinematic - Moved by you, through the entity's transform. It pushes dynamic bodies out of its way but is not affected by them or by gravity. Use it for moving platforms, doors driven by animation and anything else that follows a script rather than the laws of physics.

Here is a one meter dynamic box that will fall onto whatever is below it:

const box = new pc.Entity('box');
box.addComponent('render', { type: 'box' });
box.addComponent('collision', { type: 'box' });
box.addComponent('rigidbody', { type: pc.BODYTYPE_DYNAMIC, mass: 2 });
box.setPosition(0, 5, 0);
app.root.addChild(box);
Falling Shapes

Mass and Materials​

Four properties describe how heavy a body is and how its surface behaves in a contact:

PropertyDescription
MassThe mass of a dynamic body in kilograms. Heavier bodies need more force to accelerate and push lighter ones aside. Defaults to 1 and is ignored by static and kinematic bodies
FrictionHow strongly the surface resists sliding, from 0 to 1. Defaults to 0.5
Rolling FrictionResistance to rolling, which stops spheres and cylinders from rolling forever. Defaults to 0
RestitutionBounciness, from 0 to 1. Defaults to 0. The values of the two bodies in a contact are multiplied together, so a ball with a restitution of 1 does not bounce on a floor with a restitution of 0
entity.rigidbody.mass = 5;
entity.rigidbody.friction = 0.8;
entity.rigidbody.rollingFriction = 0.1;
entity.rigidbody.restitution = 0.6;

Damping and Factors​

Two pairs of properties shape how a dynamic body moves once it is in motion:

  • Linear Damping and Angular Damping are the proportion of velocity a body loses each second, from 0 to 1, like air resistance. They default to 0.
  • Linear Factor and Angular Factor scale movement and rotation per world axis. A factor of 0 locks that axis. Setting the angular factor to 0, 0, 0 keeps a character upright; a linear factor of 1, 1, 0 with an angular factor of 0, 0, 1 confines a body to the XY plane for a 2D game. They default to 1, 1, 1.
// Slow the body down over time, like air resistance
entity.rigidbody.linearDamping = 0.2;
entity.rigidbody.angularDamping = 0.2;

// Keep a character upright: no rotation about any axis
entity.rigidbody.angularFactor = new pc.Vec3(0, 0, 0);

// Confine a body to the XY plane of a 2D game
entity.rigidbody.linearFactor = new pc.Vec3(1, 1, 0);

Gravity Scale​

The gravity scale multiplies the world gravity for a single dynamic body. It defaults to 1, so the body falls like everything else. A value between 0 and 1 makes it fall more gently, 0 lets it float free of gravity, and a negative value makes it rise like a balloon. The scale is applied to whatever the world gravity is, so the body follows later changes to it. Static and kinematic bodies are not moved by gravity, so the property has no effect on them.

Unlike a linear factor of 0, which locks all movement along an axis, a gravity scale of 0 removes only gravity: the body still responds to collisions, forces and impulses. To give a body a gravity of its own, for example one that pulls towards the center of a small planet, set its scale to 0 and apply that force yourself every frame.

Changing the scale does not wake a sleeping body, whether you set it from code, a React prop or a Web Components attribute. A box resting on the floor stays put when given a negative scale until something disturbs it, so call activate() after changing the scale of a body that may be asleep (see Sleeping).

// Fall under half the world gravity
entity.rigidbody.gravityScale = 0.5;

// Drift slowly upwards like a balloon, waking the body in case it is asleep
entity.rigidbody.gravityScale = -0.2;
entity.rigidbody.activate();

Sleeping​

A dynamic body that comes to rest is put to sleep by the physics engine, which stops simulating it until something disturbs it. Applying a force, impulse or torque, assigning a velocity and teleporting all wake a body automatically, as does being hit by another body. You can also wake one yourself:

if (!entity.rigidbody.isActive()) {
entity.rigidbody.activate();
}

Moving and Teleporting​

A body's type decides who owns its position and rotation, and so how you move it:

TypeHow to move itWhat setting the entity's transform does
DynamicForces, impulses and velocities, or teleport to jumpNothing to the body. A moving body overwrites the change on the next step; a sleeping one is left behind
KinematicThe entity's transformThe body follows on the next step
StaticNot meant to move. teleport repositions oneNothing to the body, which stays where it was created

The calls below are the same wherever you build. In React, reach the entity with the useParent hook from a component placed inside the <Entity>; in Web Components, through the entity property of the <pc-entity> element. Moving Bodies shows where per-frame code runs on each surface.

Dynamic Bodies​

The physics engine owns the position and rotation of a dynamic body. To move one, apply forces or velocities, or call teleport on the rigidbody component when it has to jump somewhere, for example when respawning. Teleporting does not clear the body's velocity, so reset that first if the body should arrive at rest:

// Move to a position, keeping the current rotation
entity.rigidbody.teleport(0, 10, 0);

// Move and rotate, with the rotation given as Euler angles in degrees
entity.rigidbody.teleport(new pc.Vec3(0, 10, 0), new pc.Vec3(0, 90, 0));

// Respawn at rest: clear the old motion, then move and rotate with a quaternion
entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
entity.rigidbody.teleport(spawn.getPosition(), spawn.getRotation());

Vector properties such as linearVelocity and angularFactor return read-only snapshots. Assign a new vector rather than editing the returned one.

Kinematic Bodies​

Kinematic bodies work the other way round. You move the entity with setPosition, setRotation, lookAt and the rest of the transform API, and the body follows on the next step, carrying any dynamic bodies that rest on it:

// A platform that slides back and forth along the X axis
platform.setPosition(Math.sin(time) * 2, 0.5, 0);

Static Bodies​

The engine reads a static body's position and rotation from its entity when the body is created, and never checks them again. Not tracking static bodies is part of what makes them cheap, but it means that moving or rotating the entity during play leaves the body behind: the model moves, and other bodies keep colliding with an invisible shape where it used to be.

If an object moves during play, such as a door or a lift, make it kinematic. To reposition a static body now and then, for example when a level is rearranged, call teleport, which moves the entity and its body together:

// Move a static wall, and its body, to a new position
wall.rigidbody.teleport(0, 0, 10);

Teleporting a static body does not wake the bodies resting on it. Any that have fallen asleep stay where they are, even if that leaves them floating in the air.

Scaling​

A rigid body has a position and a rotation but no scale, so scaling its entity does not resize the body. Its size comes from its collision shape. Resize a box, sphere, capsule, cylinder or cone through properties such as its half extents or radius; the body is rebuilt at the new size and keeps moving. Mesh shapes are the exception, and follow the entity's scale. Scale on the Collision Shapes page explains why, with the details for each kind of shape.

Collision Groups and Masks​

Every body belongs to a collision group and carries a mask of the groups it collides with. Two bodies interact only when each one's group is in the other's mask. The engine assigns both when the body type is set: dynamic bodies collide with everything, while static and kinematic bodies never collide with each other. You can narrow this from code to stop, for example, projectiles hitting one another:

// Put the body in a user group and stop it colliding with other members of that group.
// Set these after the type, because changing the type resets them.
entity.rigidbody.group = pc.BODYGROUP_USER_1;
entity.rigidbody.mask = pc.BODYMASK_ALL ^ pc.BODYGROUP_USER_1;

Eight user groups, pc.BODYGROUP_USER_1 to pc.BODYGROUP_USER_8, are free for your own use. The same groups and masks filter ray casts.

See Also​