Playcanvas physics extension

Sometimes there comes a need to detect a collision, when simple raycast is not suitable. For example, when you want to check if camera sphere can fit into that new location, or a car can pass between two trees without hitting them.

To manage such cases, you would want to cast a sphere along the path or some sort of a shape, that would detect the collision. I’ve made a physics extension to do just that:

Example project. (Click to change shapes. An invisible shape is a custom shape - convex triangle. Check example sources for details.)

How to install
No intallation needed. Just download rigidbody-extensions.js from the example project and drop it anywhere in your project.

How to use
You can refer to example.js to see how to cast a shape for collision detection.

// Example sphere cast:
// radius - sphere radius
// start - position from where to start the cast
// end - position where the cast should end
var result =, start, end);
// result will contain the sweep test result or null if no collision

Supported shapes

Sphere:       .sphereCast(radius, start, end)
Cone:         .coneCast(radius, height, start, end)
Box:          .boxCast(halfExtents, start, end)
Cylinder:     .cylinderCast(halfExtents, start, end)
Capsule:      .capsuleCast(radius, height, start, end)
Custom shape: .shapeCast(vertices, start, end)

Advanced use
The .shapeCast() method shows how to create your own custom convex shape and use it for the sweep test. Here, I provide 3 consecutive vertices, which comprise a triangle shape:

var triangle = new Float32Array([ 1, -1, 0, -1, -1, 0, 0, 1, 0 ]);
result =, start, end);

All of the mentioned methods for shape casting are simply convenience methods that use one method only.;

Their responsibility is to generate a desired shape and pass it to the .convexCast() method for sweep test. It requires to be passed a shape, starting position of the sweep and the end position. All other arguments are optional:

@param {Ammo shape} shape - Convex shape used for sweep test.
@param {pc.Vec3} startPos - The world space point where the hit test starts.
@param {pc.Vec3} endPos - The world space point where the test ends.
@param {pc.Quat} [startRot] - Initial rotation of the shape.
@param {pc.Quat} [endRot] - Final rotation of the shape.
@param {number} [allowedPenetration] - CCD allowance margin.
@param {boolean} [findEntity] - Flag to do a separate raycast to return an entity.


  • Some shape methods take an optional margin attribute. It is for adjusting the collision shape margin, for example, you can make rounded corners in a box shape. The engine sets a default safe margin value (something like 0.03-0.04). If your shape is very small, you would want to adjust it.
  • You can optionally specify the initial and final rotations of the shape by providing the related pc.Quat quaternions. The extesion will default the rotations of the shape to face towards the end position of the sweep.
  • The collision detection is performed using the CCD method, which allows you to provide a collision penetration allowance via allowedPenetration attribute. If your object is moving at high speed, you would want to adjust this value to avoid passing through an obstacle. Defaults to 0.
  • By default the result will provide you the point in world space where collision occured, the normal of the surface that was hit and the hit fraction. The hit fraction is basically a normalized value of the sweep path location, where the collision occured. For example, it will be 0.5 if the collision occured in the middle of the sweep path.
  • The method allows you to make a separate rraycast test to find the entity at the hit point. You can pass findEntity as true to include the hit entity into the cast result. Deafults to false, because it is expensive.
  • Some shape generation methods accept an optional orientation axis. You can provide pc.Vec3.RIGHT to generate the shape around the X axis, or pc.Vec3.BACK for Z axis. Defaults to pc.Vec3.UP.

Pretty cool.

There is a known issue with my extension that Ammo will occasionally throw an OOM assertion when you do a convex sweep test. I am not sure what is causing it. I will probably need to build Ammo with debug enabled flags for that and see if this is something I can fix. Also, if you notice a bug in my convexCast() method, please, let me know.

Just be aware and use with caution untill then.

I think I found the cause. Most probably OOM is thrown because I need to re-use the shape objects I am generating, instead of creating new ones. Fix will come.