Lightweight .NET physics engine featuring broadphase (dynamic AABB tree) and narrowphase (GJK+EPA) collision detection plus simple rigid body dynamics.
$ dotnet add package PhysNetA lightweight 3D physics engine for .NET 8, written in C#.
ITransform interface allowing integration with custom transform implementationsShape base class for implementing custom collision shapesusing PhysNet.World;
using PhysNet.Math;
using System.Numerics;
// Create physics world
var world = new PhysicsWorld();
world.Gravity = new Vector3(0, -9.81f, 0);
// Create a dynamic sphere
var sphere = Physics.CreateDynamicSphere<Transform>(0.5f, 1.0f, new Vector3(0, 10, 0));
world.AddBody(sphere);
// Create static ground
var ground = Physics.CreateStaticBox<Transform>(new Vector3(10, 0.5f, 10), new Vector3(0, -0.5f, 0));
world.AddBody(ground);
// Run simulation
for (int i = 0; i < 60; i++)
{
world.Step(1.0f / 60.0f);
Console.WriteLine($"Sphere Y: {sphere.Transform.Position.Y:F2}");
}
The main simulation class that manages rigid bodies, collision detection, and constraint solving.
var world = new PhysicsWorld();
world.Gravity = new Vector3(0, -9.81f, 0);
world.SolverIterations = 10;
// Configure solver settings
world.SolverSettings.Baumgarte = 0.2f;
world.SolverSettings.PenetrationSlop = 0.01f;
world.SolverSettings.FrictionCombine = CombineMode.Average;
world.SolverSettings.RestitutionCombine = CombineMode.Max;
Represents objects in the physics simulation with collision shapes, transforms, and dynamic properties.
var shape = new SphereShape(0.5f);
var transform = new Transform(new Vector3(0, 5, 0), Quaternion.Identity);
var body = new RigidBody(shape, 1.0f, transform);
// Configure motion type and collision properties
body.MotionType = MotionType.Dynamic;
body.LinearDamping = 0.01f;
body.AngularDamping = 0.05f;
body.Group = CollisionMask.Dynamic;
body.Mask = CollisionMask.All;
PhysNet uses an ITransform interface for maximum flexibility:
// Use built-in Transform struct
ITransform transform = new Transform(position, rotation);
// Or implement custom transforms
public class CustomTransform : ITransform
{
public Vector3 Position { get; set; }
public Quaternion Rotation { get; set; }
public System.Action OnTransformChanged { get; set; }
// Add custom functionality...
}
Available primitive shapes with automatic mass property computation:
var sphere = new SphereShape(0.5f);
var box = new BoxShape(new Vector3(1, 2, 0.5f));
var capsule = new CapsuleShape(0.3f, 1.0f);
var cylinder = new CylinderShape(0.4f, 1.5f);
// Shapes compute their own inertia and center of mass
shape.ComputeInertia(mass, out Matrix4x4 inertia, out Vector3 centerOfMass);
world.SolverSettings.Iterations = 10; // Constraint solver iterations
world.SolverSettings.Baumgarte = 0.2f; // Position correction factor
world.SolverSettings.PenetrationSlop = 0.01f; // Allowed penetration before correction
world.SolverSettings.FrictionCombine = CombineMode.Average;
world.SolverSettings.RestitutionCombine = CombineMode.Max;
shape.Friction = 0.5f; // Surface friction coefficient
shape.Restitution = 0.3f; // Bounciness (0 = inelastic, 1 = perfectly elastic)
body.Group = CollisionMask.Dynamic; // What groups this body belongs to
body.Mask = CollisionMask.All; // What groups this body can collide with
// Bodies collide if: (bodyA.Group & bodyB.Mask) != 0 && (bodyB.Group & bodyA.Mask) != 0
PhysNet/
├── Math/ # Transform system and mathematical utilities
├── Collision/
│ ├── Shapes/ # Collision shape implementations
│ ├── Broadphase/ # Dynamic AABB tree and culling
│ └── Narrowphase/ # GJK/EPA collision detection
├── Dynamics/ # Rigid body and constraint solver
└── World/ # Physics world and utility functions
This is a hobby project. See LICENSE file for details.
This engine implements concepts from: