Each tier is built on the one below, so you can start at the top and drop down for one object without rewriting the rest.
1. The happy path
new PhysicsWorld2D(), world.AddBox(size, at: ...), body.OnCollisionEnter += ..., world.Raycast(...), world.AddCharacter(...), world.Step(dt). Unity's vocabulary, full sizes, radians, sensible defaults (gravity -9.81, four substeps, friction 0.6, sleeping on). Nothing here asks you to implement an interface or write a generic struct. See the quick start.
Filtering on this tier is a layer matrix (body.Layer, world.IgnoreLayerCollision(a, b)) plus an optional delegate (WorldOptions2D.PairFilter, a PairPredicate) and query filters with an optional predicate. See queries, layers and filters.
2. The middle tier
Definitions with defaults, polled events, a reusable query object, struct callbacks and solver control.
BodyDef,ShapeDefand the joint definitions are valid at their zero value and then mean their documented defaults (new ShapeDef { Friction = 0.9f }changes only friction). They are structs; fill one, then pass it toCreateBody,CreateBoxand the otherCreate*methods, orCreateJoint(ref ...). TheAdd*one-liners are thin wrappers over these.WorldOptions2D(WorldOptions3Din 3D): gravity,Substeps,VelocityIterations,RelaxIterations, sleep settings, the event mask,ThreadCount,WorldIdand capacity options. Substep and iteration counts are inputs of the simulation, never chosen from the clock or the machine.GetEvents(kind)andEventsreturn the events of the last step as a span, with no allocation.PhysicsQuery2D/PhysicsQuery3Dhold a world and a filter and add batch forms that run many queries in parallel.SetContactFilter<T>(T filter) where T : struct, IContactFilterdecides per shape pair, specialized for your struct.
struct NotTheSameBody : IContactFilter { public bool ShouldCollide(Shape a, Shape b) => a.Body != b.Body; }
var world = new PhysicsWorld2D(new WorldOptions2D { Gravity = new Vector2F(0, -9.81f), Substeps = 4, // substeps per Step call VelocityIterations = 1, // solve passes with bias per substep RelaxIterations = 1, // relax passes without bias per substep }); var floor = world.CreateBody(new BodyDef { Type = BodyType.Static, Position = new Vector2D(0, -0.5) }); world.CreateBox(floor, new Vector2F(20, 1), def: new ShapeDef { Friction = 0.9f, Layer = 1 }); var box = world.CreateBody(new BodyDef { Position = new Vector2D(0, 2), Angle = 0.3f }); world.CreateBox(box, new Vector2F(1, 1), def: new ShapeDef { Density = 2f, Restitution = 0.1f, Layer = 2 }); world.IgnoreLayerCollision(2, 3); world.SetContactFilter(new NotTheSameBody()); for (int i = 0; i < 60; i++) { world.Step(1f / 60); foreach (var e in world.GetEvents(EventKind.ContactBegin)) { Console.WriteLine($"{world.GetBody(e.BodyA)} touched {world.GetBody(e.BodyB)}"); } } var query = new PhysicsQuery2D(world) { Filter = QueryFilter2D.OnLayer(1) }; var hits = new QueryHit2D[16]; int n = query.RaycastAll(new Vector2D(-5, -0.25), new Vector2F(1, 0), hits);
The contact filter is not saved in snapshots: install it again after Restore.
Joints follow the same pattern: the one-liner (AddHinge) or a definition (RevoluteJointDef) returns a typed view (HingeJoint) that converts implicitly to Joint. A member another kind of joint has does not compile on the view. See names and conventions for the table.
3. The raw tier
RecursiveAI.OnePhysics.LowLevel: struct-of-arrays body and constraint storage, the constraint coloring and scheduler, broadphase trees, narrowphase and manifold routines, snapshot readers and writers. It is [Experimental("OPHYS0001")]: using it needs <NoWarn>$(NoWarn);OPHYS0001</NoWarn>, and it may change between previews. Use it when you build your own pipeline; nothing on tiers 1 and 2 requires it. The behaviour it implements is written down in ../spec.
Namespaces
RecursiveAI.OnePhysics: what game code names in both dimensions:BodyType,EventKind,EventMask,PhysicsEvent,OptionChanges, the raw handles (BodyHandle,ShapeHandle,JointHandle) and the exceptions.RecursiveAI.OnePhysics.Physics2DandPhysics3D: the world,Body,Shape,Joint,Character, definitions, queries and options. Both use the same member names.RecursiveAI.OnePhysics.Debug: debug geometry (shapes, contacts, joints, islands, broadphase bounds) as plain data for you to draw.RecursiveAI.OnePhysics.LowLevel: the raw tier.