Use this file to discover all available pages before exploring further.
The s&box physics system gives you direct access to rigid-body simulation through PhysicsBody, world-level configuration via PhysicsWorld, geometry queries through PhysicsTrace, collision shapes with PhysicsShape, and constraints using PhysicsJoint and PhysicsSpring. This page covers how to create and work with each of these types in your C# components.
The scene automatically creates and manages a PhysicsWorld for you. You only need to instantiate one yourself if you want to run a secondary, isolated simulation.
PhysicsWorld is the container for all physics simulation. Every active scene owns one. You can access it via a component’s Scene.PhysicsWorld property.
// Adjust gravity for a low-gravity levelScene.PhysicsWorld.Gravity = new Vector3( 0, 0, -200 );// Enable continuous collision detection (default)Scene.PhysicsWorld.SimulationMode = PhysicsSimulationMode.Continuous;// Increase sub-steps for better stacking stability at low tick ratesScene.PhysicsWorld.SubSteps = 2;
Gravity
Set Gravity as a Vector3. The default points downward along Z.
SimulationMode
Continuous (default) prevents fast objects tunnelling through thin walls. Discrete is cheaper but less accurate.
SubSteps
Break each tick into multiple steps. Higher values improve stacking stability at the cost of CPU.
SleepingEnabled
Bodies automatically sleep after a period of inactivity. Disable if you need every body to tick every frame.
Shapes define the collision geometry. A body supports any combination of primitives.
// Spherebody.AddSphereShape( Vector3.Zero, radius: 16.0f );// Box — position and rotation are relative to the body originbody.AddBoxShape( Vector3.Zero, Rotation.Identity, new Vector3( 32, 32, 32 ) );// Capsule — two end-cap centres plus radiusbody.AddCapsuleShape( Vector3.Down * 32, Vector3.Up * 32, radius: 16.0f );// Convex hull from point cloudbody.AddHullShape( Vector3.Zero, Rotation.Identity, points );// Mesh — static collision only; cannot be simulatedbody.AddMeshShape( vertices, indices );
Use impulses for discrete events like bullet impacts or explosions.
// Apply at centre of massbody.ApplyImpulse( Vector3.Up * 500 );// Apply at a world-space point (adds torque)body.ApplyImpulseAt( hitPosition, Vector3.Up * 500 );// Angular impulse (spin)body.ApplyAngularImpulse( new Vector3( 0, 0, 100 ) );
Forces are accumulated and applied once per physics tick, scaled by the timestep.
// Called each physics framebody.ApplyForce( new Vector3( 0, 0, 9.81f ) * body.Mass ); // anti-gravitybody.ApplyForceAt( thrusterPosition, thrustVector );body.ApplyTorque( torqueVector );
Use SmoothMove to drag a body toward a target without breaking the simulation — ideal for grab mechanics.
// Ignore a specific tagvar result = Scene.PhysicsWorld.Trace .Ray( start, end ) .IgnoreStatic() // skip world geometry .Run();// Custom per-shape callbackvar result = Scene.PhysicsWorld.Trace .Ray( start, end ) .Filter( shape => shape.Body != myOwnBody ) .Run();// Include trigger volumesvar result = Scene.PhysicsWorld.Trace .Ray( start, end ) .HitTriggers() .Run();
var hits = Scene.PhysicsWorld.Trace .Sphere( 32.0f, start, end ) .RunAll();foreach ( var hit in hits ){ Log.Info( $"Hit at fraction {hit.Fraction}" );}
using Sandbox.Physics;var joint = PhysicsJoint.CreateFixed( bodyA.WorldPoint( attachA ), bodyB.WorldPoint( attachB ));// Limit the force before the joint breaksjoint.Strength = 5000.0f;joint.AngularStrength = 3000.0f;// React when it breaksjoint.OnBreak += () => Log.Info( "Joint broke!" );
// Rope — no minimum, enforces maximum lengthvar rope = PhysicsJoint.CreateLength( bodyA.LocalPoint( Vector3.Zero ), bodyB.LocalPoint( Vector3.Zero ), maxLength: 200.0f);// Spring — bounces between min and max like a bungee cordvar spring = PhysicsJoint.CreateSpring( bodyA.LocalPoint( Vector3.Zero ), bodyB.LocalPoint( Vector3.Zero ), minLength: 50.0f, maxLength: 150.0f);
// Bodies rotate around their local X axisvar hinge = PhysicsJoint.CreateHinge( bodyA.LocalPoint( pivotLocal ), bodyB.LocalPoint( pivotLocal ));hinge.Collisions = false; // prevent the two bodies colliding with each other
PhysicsSpring configures the softness and damping of a joint. It applies to FixedJoint and can be used wherever spring parameters are accepted.
var spring = new PhysicsSpring( frequency: 5.0f, // stiffness — oscillations per second damping: 0.7f, // 0 = no damping, 1 = critically damped maximum: 1000.0f // maximum force (for weld joints));
The following component creates a dynamic physics prop on OnStart, applies an explosion impulse, and logs when it collides with something.
using Sandbox;using Sandbox.Physics;public class PhysicsProp : Component{ PhysicsBody _body; protected override void OnStart() { _body = new PhysicsBody( Scene.PhysicsWorld ); _body.BodyType = PhysicsBodyType.Dynamic; _body.Position = WorldPosition; _body.Component = this; _body.Mass = 5.0f; _body.AddBoxShape( Vector3.Zero, Rotation.Identity, new Vector3( 24, 24, 24 ) ); _body.EnableTouch = true; _body.OnIntersectionStart = OnHit; // Throw upward _body.ApplyImpulse( Vector3.Up * 800 ); } protected override void OnFixedUpdate() { // Keep the visual object in sync with the physics body WorldPosition = _body.GetLerpedTransform( Time.Now ).Position; WorldRotation = _body.Rotation; } void OnHit( PhysicsIntersection c ) { Log.Info( $"Hit at {c.Contact.Point} with speed {c.Contact.NormalSpeed}" ); } protected override void OnDestroy() { _body?.Remove(); }}
Call body.GetLerpedTransform( Time.Now ) to get a smoothly interpolated transform between physics ticks. This prevents visible jitter when the render rate is higher than the physics tick rate.