Recursive AI

2D physics in C#

All onephysics recipes

Create a PhysicsWorld2D, add bodies with one call each, and call Step once per frame with a fixed time step. The program below builds a stack of five crates, knocks it down with a rubber ball, and prints where everything is after each simulated second.

Terminal
dotnet new console -o Physics2D && cd Physics2D
dotnet add package RecursiveAI.OnePhysics --version 0.4.0-preview.1

Put this in Program.cs and run dotnet run:

C#
using RecursiveAI.OneMath;               // Vector2F, Vector2D
using RecursiveAI.OnePhysics;            // BodyType
using RecursiveAI.OnePhysics.Physics2D;  // PhysicsWorld2D, Body, Material2D
 
var world = new PhysicsWorld2D();        // gravity -9.81 m/s² along y
 
// The ground: a static 40 m x 1 m box whose top is at y = 0.
world.AddBox(new Vector2F(40, 1), at: new Vector2D(0, -0.5), type: BodyType.Static);
 
// Five 1 m crates stacked at x = 5.
var crates = new List<Body>();
for (int i = 0; i < 5; i++)
    crates.Add(world.AddBox(new Vector2F(1, 1), at: new Vector2D(5, 0.5 + i)));
 
// A rubber ball thrown from the left at 25 m/s.
Body ball = world.AddCircle(0.5f, at: new Vector2D(-5, 2),
                            material: Material2D.Rubber);
ball.SetLinearVelocity(new Vector2F(25, 1));
 
const float dt = 1f / 60;                // one fixed step per frame
for (int frame = 1; frame <= 240; frame++)
{
    world.Step(dt);
    if (frame % 60 != 0) continue;
    Vector2D b = ball.Position, top = crates[4].Position;
    Console.WriteLine($"t={frame / 60}s ball ({b.X:F2}, {b.Y:F2})  "
        + $"top crate ({top.X:F2}, {top.Y:F2})");
}
Console.WriteLine($"world hash {world.ComputeHash():X16}");
Text
t=1s ball (0.96, 2.01)  top crate (4.71, 4.77)
t=2s ball (-4.46, 1.27)  top crate (3.71, 1.37)
t=3s ball (-9.84, 1.11)  top crate (3.30, 0.50)
t=4s ball (-15.26, 0.60)  top crate (3.30, 0.50)
world hash 691636F9904A86B1

The ball hits the stack, knocks the top crate off and bounces back to the left; by t=3s the crate lies on the ground (y = 0.5, its half height). Sizes are full extents in meters, positions are double (Vector2D) and everything else is float. Bodies are dynamic unless you pass BodyType.Static or Kinematic, and they fall asleep when they come to rest. Draw each body at its Position and Angle after every Step.

The world hash is the point of OnePhysics: run the same steps on another OS, CPU or in the browser and it prints the same hash, so a lockstep or rollback game stays in sync. See Rollback physics in C#.

What else is there

  • Shapes: AddCircle, AddBox, AddCapsule, AddPolygon, AddSegment and AddChain for terrain.
  • Materials: Material2D.Rubber, Ice, Metal and Wood, or new Material2D(friction, restitution, rollingResistance).
  • Forces: ApplyForce, ApplyImpulse, ApplyTorque, SetLinearVelocity.
  • Collisions: events such as OnCollisionEnter (events and sensors), raycasts and overlap tests (Raycasts in 2D physics), and joints (Joints).
  • Characters: AddCharacter gives a character mover that walks, stands on slopes and resolves its own contacts: see getting started.

Limits

  • OnePhysics is a preview (0.4.0-preview.1, .NET 10) and is paused for now. The API and results may change between previews, and a snapshot or replay from one preview doesn’t load in the next.
  • One fixed time step. Use one dt for the whole session; a variable frame time changes the results.
  • 2D is the supported engine. The 3D engine is a preview inside the preview: see the 3D preview.