Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ProwlEngine/Prowl/llms.txt

Use this file to discover all available pages before exploring further.

Colliders are the physical shapes that the Jitter2 simulation uses to detect contact between objects. Every Rigidbody3D gathers all Collider components on itself and its children to build a composite body — you never need to call shape-creation APIs manually. Prowl ships eight collider types covering everything from simple primitives to arbitrary triangle-mesh geometry, plus an experimental WheelCollider for vehicle simulations. Choosing the right collider type for each object keeps your physics simulation fast and predictable.

How Colliders Work with Rigidbody3D

A Collider on its own has no effect. It must live on the same GameObject as a Rigidbody3D, or anywhere in the GameObject’s child hierarchy. When the Rigidbody3D is enabled — or when any collider is added, removed, or changed at runtime — Rigidbody3D.UpdateShapes() regenerates the entire body shape automatically.
Multiple colliders on a single Rigidbody3D are composed into a compound body. Each collider’s center and rotation offsets are applied in the rigid body’s local space, making compound shapes easy to build without additional code.
The base Collider class exposes two shared offset fields:
FieldTypeDescription
centerVector3Local-space positional offset of the shape relative to the parent rigid body.
rotationVector3Euler-angle rotation offset applied to the shape in local space.
Any change to center or rotation triggers OnValidateRigidbody3D.OnValidate(), instantly refreshing the physics body in the editor and at runtime.

Primitive Colliders

Primitive colliders map directly to Jitter2’s analytic shapes and are the cheapest option for collision detection. Always prefer a primitive over a mesh collider when your geometry is close enough to one of these forms.

BoxCollider

A solid axis-aligned box. Set the Size vector to match the dimensions of your mesh in metres.

SphereCollider

A perfect sphere. Ideal for balls, grenades, and rounded objects. Set Radius in metres.

CapsuleCollider

A cylinder with hemispherical end-caps. The standard shape for humanoid characters. Controlled by Radius and Height.

CylinderCollider

A flat-capped cylinder. Useful for wheels, columns, and cans. Controlled by Radius and Height.

ConeCollider

A cone shape with a single apex. Controlled by Radius and Height.

BoxCollider

BoxCollider box = gameObject.AddComponent<BoxCollider>();
box.Size   = new Vector3(2.0f, 1.0f, 0.5f); // width × height × depth (metres)
box.center = new Vector3(0, 0.5f, 0);        // lift the box half a metre

SphereCollider

SphereCollider sphere = gameObject.AddComponent<SphereCollider>();
sphere.Radius = 0.5f; // half-metre radius

CapsuleCollider

CapsuleCollider capsule = gameObject.AddComponent<CapsuleCollider>();
capsule.Radius = 0.4f; // body radius
capsule.Height = 1.8f; // total height including end-caps

CylinderCollider

CylinderCollider cylinder = gameObject.AddComponent<CylinderCollider>();
cylinder.Radius = 0.3f;
cylinder.Height = 1.2f;

ConeCollider

ConeCollider cone = gameObject.AddComponent<ConeCollider>();
cone.Radius = 0.5f;
cone.Height = 1.5f;

Mesh-Based Colliders

Use mesh colliders when your geometry cannot be approximated by a primitive. There are two variants with different performance and accuracy trade-offs.
Builds a convex hull from all vertices in the referenced Mesh using Jitter2’s ConvexHullShape. This is a single shape, so it is fast and can be used on dynamic (non-static) bodies. It cannot represent concave geometry.
ConvexHullCollider hull = gameObject.AddComponent<ConvexHullCollider>();

// Assign a mesh reference — the collider auto-fetches from MeshRenderer if left null
hull.Mesh = myMeshAsset;
If Mesh is not assigned the component will fall back to reading the Mesh from a sibling MeshRenderer component on Awake.
Do not use MeshCollider on dynamic rigid bodies. The triangle-mesh shape does not support mass-inertia calculations correctly and will produce unpredictable simulation results. Use ConvexHullCollider for dynamic mesh-shaped objects instead.

WheelCollider (Experimental)

WheelCollider is a specialised component that simulates a raycast-based vehicle wheel with suspension, side-slip friction, and drive torque. It does not extend Collider — it is a standalone MonoBehaviour that must be placed on a child GameObject of the vehicle’s Rigidbody3D.
WheelCollider is marked experimental. The forward-friction code path is partially commented out in the source while the model is being refined.
// Retrieve wheels and auto-tune suspension for a 4-wheel vehicle
WheelCollider[] wheels = GetComponentsInChildren<WheelCollider>();
foreach (var w in wheels)
    w.AdjustWheelValues(); // calculates Spring, Damping, Inertia from body mass

// Drive the front wheels each FixedUpdate
public override void FixedUpdate()
{
    float throttle = Input.GetAxis("Vertical");
    wheels[0].AddTorque(throttle * engineTorque);
    wheels[1].AddTorque(throttle * engineTorque);

    // Steer the front wheels
    float steer = Input.GetAxis("Horizontal") * maxSteerAngle;
    wheels[0].SteerAngle = steer;
    wheels[1].SteerAngle = steer;
}
Key WheelCollider properties:
PropertyDefaultDescription
Radius0.5Wheel radius in metres.
SuspensionTravel0.2Maximum vertical suspension travel (metres).
Spring35000Suspension spring stiffness (N/m).
Damping1500Suspension damping coefficient (N·s/m).
Inertia5Rotational inertia of the wheel (kg·m²).
SideFriction3.2Lateral friction multiplier.
SteerAngle0Yaw offset applied when casting contact rays (degrees).
IsLockedfalseWhen true, the wheel is braked — angular velocity is zeroed.
IsGrounded(read-only)true when at least one ray hit the ground last step.
WheelRotation(read-only)Accumulated wheel rotation angle (radians).

Compound Colliders

Attach multiple collider components to a single Rigidbody3D (on the same or child GameObjects) to model complex shapes. The rigid body iterates all Collider components via GetComponents<Collider>() and composites their shapes using TransformedShape to preserve each collider’s offset and rotation.
// A capsule body with a small box for a backpack
var rb = gameObject.AddComponent<Rigidbody3D>();
rb.Mass = 80.0;

// Main body
var body = gameObject.AddComponent<CapsuleCollider>();
body.Radius = 0.35f;
body.Height = 1.75f;

// Backpack offset backward and up
var pack = gameObject.AddComponent<BoxCollider>();
pack.Size   = new Vector3(0.4f, 0.5f, 0.2f);
pack.center = new Vector3(0f, 0.6f, -0.25f);
You can enable and disable individual Collider components at runtime. Each toggle calls rb.OnValidate() internally, which rebuilds the compound shape on the fly — no manual bookkeeping required.

Setting Up a Character

1

Create the GameObject

Add an empty GameObject to your scene and name it Player.
2

Add Rigidbody3D

Add Component → Physics → Rigidbody3D. Set Mass to 80 and leave AffectedByGravity enabled.
3

Add CapsuleCollider

Add Component → Physics → Capsule Collider. Set Radius to 0.35 and Height to 1.75. Offset center to (0, 0.875, 0) so the bottom of the capsule sits at the object’s origin.
4

Tune material

Set Friction to 0.4 and Restitution to 0 on the Rigidbody3D so the character slides smoothly without bouncing.
5

Script movement

Use rb.Velocity or rb.AddForce in your movement component, and a downward Physics.Raycast for ground detection.
using Prowl.Runtime;

public class CharacterController : MonoBehaviour
{
    public double moveSpeed = 5.0;
    public double jumpForce = 8.0;
    private Rigidbody3D _rb;
    private bool _isGrounded;

    public override void Awake()
    {
        _rb = GetComponent<Rigidbody3D>();
    }

    public override void FixedUpdate()
    {
        // Ground check
        _isGrounded = Physics.Raycast(
            Transform.position,
            Vector3.down,
            out _,
            0.95);

        // Horizontal movement
        double h = Input.GetAxis("Horizontal");
        double v = Input.GetAxis("Vertical");
        Vector3 move = new Vector3(h, 0, v) * moveSpeed;
        _rb.Velocity = new Vector3(move.x, _rb.Velocity.y, move.z);

        // Jump
        if (_isGrounded && Input.GetKeyDown(KeyCode.Space))
        {
            Vector3 vel = _rb.Velocity;
            _rb.Velocity = new Vector3(vel.x, jumpForce, vel.z);
        }
    }
}

Build docs developers (and LLMs) love