Ahwoo.BRUTAL.Jolt
2026.10.2
Prefix Reserved
dotnet add package Ahwoo.BRUTAL.Jolt --version 2026.10.2
NuGet\Install-Package Ahwoo.BRUTAL.Jolt -Version 2026.10.2
<PackageReference Include="Ahwoo.BRUTAL.Jolt" Version="2026.10.2" />
<PackageVersion Include="Ahwoo.BRUTAL.Jolt" Version="2026.10.2" />
<PackageReference Include="Ahwoo.BRUTAL.Jolt" />
paket add Ahwoo.BRUTAL.Jolt --version 2026.10.2
#r "nuget: Ahwoo.BRUTAL.Jolt, 2026.10.2"
#:package Ahwoo.BRUTAL.Jolt@2026.10.2
#addin nuget:?package=Ahwoo.BRUTAL.Jolt&version=2026.10.2
#tool nuget:?package=Ahwoo.BRUTAL.Jolt&version=2026.10.2
Brutal Jolt
Highly experimental early version of Brutal Jolt. The current interface works but is subject to many changes. Refer to InteropStatus.md for details about the state of this project.
C# bindings for the Jolt Physics engine, for use with the BRUTAL framework.
Brutal Jolt exposes Jolt Physics — a high-performance 3D rigid body simulation engine designed for games — through an idiomatic .NET API. Use it to add collision detection, rigid body dynamics, constraints, character controllers, and vehicle physics to BRUTAL games. Jolt is designed for deterministic simulation and scales well across multiple CPU cores.
Platform Support
- Windows (x64)
- Linux (x64)
- macOS (Apple Silicon)
Links
NuGet Packages
- Ahwoo.BRUTAL.Jolt - C# bindings for the Jolt Physics engine
For Users
Installation
To install the package via NuGet, run the following command in your project directory:
dotnet add package Ahwoo.BRUTAL.Jolt
Usage
The API lives in the Brutal.JoltApi namespace. A minimal setup looks like this (see samples/Brutal.Jolt.Samples for complete working scenes):
1. Initialize once at startup
using Brutal.JoltApi;
using Brutal.Numerics;
// Global Jolt registration
Jolt.RegisterDefaultAllocator();
Factory.Instance = Factory.Create();
Jolt.RegisterTypes();
// Scratch memory and worker threads used by every physics update
var tempAllocator = TempAllocatorImpl.Create(32 * 1024 * 1024);
var jobSystem = JobSystemThreadPool.Create(2048, 8, -1);
// Two object layers (static and moving) mapped onto two broadphase layers
const ushort StaticLayer = 0;
const ushort MovingLayer = 1;
var broadPhaseLayers = BroadPhaseLayerInterfaceTable.Create(2, 2);
broadPhaseLayers.MapObjectToBroadPhaseLayer(StaticLayer, 0);
broadPhaseLayers.MapObjectToBroadPhaseLayer(MovingLayer, 1);
var layerPairFilter = ObjectLayerPairFilterTable.Create(2);
layerPairFilter.EnableCollision(StaticLayer, MovingLayer);
layerPairFilter.EnableCollision(MovingLayer, MovingLayer);
var broadPhaseFilter = ObjectVsBroadPhaseLayerFilterTable.Create(broadPhaseLayers, 2, layerPairFilter, 2);
var physicsSystem = PhysicsSystem.Create();
physicsSystem.Init(
maxBodies: 1024,
numBodyMutexes: 0,
maxBodyPairs: 65536,
maxContactConstraints: 20480,
broadPhaseLayers,
broadPhaseFilter,
layerPairFilter);
var bodyInterface = physicsSystem.GetBodyInterface();
2. Add bodies
Create a shape from its *ShapeSettings, wrap it in BodyCreationSettings, and hand it to the BodyInterface:
Every handle a call returns is yours to Dispose, unless its doc comment says it's borrowed
(e.g. physicsSystem.GetBodyInterface()). Shapes and shape settings are reference counted,
so once a body holds the shape you can let your own handles go; BodyCreationSettings is a plain
allocation and can be disposed as soon as the body exists.
// Static floor
using var floorShapeSettings = BoxShapeSettings.Create(new float3(50f, 1f, 50f), 0.05f, default);
using var floorShape = floorShapeSettings.CreateShape();
using var floorSettings = BodyCreationSettings.Create(
floorShape, new float3(0f, -1f, 0f), floatQuat.Identity, EMotionType.Static, StaticLayer);
bodyInterface.CreateAndAddBody(floorSettings, EActivation.DontActivate);
// Dynamic box dropped from above
using var boxShapeSettings = BoxShapeSettings.Create(new float3(0.5f), 0.05f, default);
using var boxShape = boxShapeSettings.CreateShape();
using var boxSettings = BodyCreationSettings.Create(
boxShape, new float3(0f, 5f, 0f), floatQuat.Identity, EMotionType.Dynamic, MovingLayer);
var boxId = bodyInterface.CreateAndAddBody(boxSettings, EActivation.Activate);
// After adding many bodies at startup
physicsSystem.OptimizeBroadPhase();
3. Step and read back each frame
physicsSystem.Update(1f / 60f, 1, tempAllocator, jobSystem);
bodyInterface.GetPositionAndRotation(boxId, out var position, out var rotation);
Step with a fixed timestep (accumulate your frame delta and call Update in 1/60s increments). The BodyInterface also covers per-frame manipulation: SetLinearVelocity, SetPositionAndRotation, ActivateBody, and friends.
When shutting down, RemoveBody/DestroyBody each body, then dispose in this order: the physics system, the three layer tables (broadPhaseFilter, layerPairFilter, broadPhaseLayers - the system holds raw pointers to them), the job system and the temp allocator. Finish with Jolt.UnregisterTypes() and Factory.DestroyInstance(); the factory belongs to the global once assigned, so don't Dispose it yourself. Handles you get back from getters such as physicsSystem.GetBodyInterface() are borrowed and say so in their doc comment; don't dispose those either.
For more detail see the BRUTAL Documentation and the Jolt Physics documentation.
Samples
The samples/Brutal.Jolt.Samples project contains three runnable entries:
- BasicCollision — A pyramid of dynamic cubes on a static ground plane, knocked down by a projectile fired with Space. The simplest end-to-end example of world setup, body creation, and per-frame transform readback.
- FirstPersonShooter — A first-person playground: a kinematic capsule player (WASD + mouse) walking among ramps and primitive targets, with a gun that fires physical projectiles.
- JoltSamples — A scene browser hosting ports of the native Jolt sample scenes (stacks, constraints, friction, restitution, and more), switchable at runtime from a dropdown.
Prerequisites
- .NET SDK (version 10.0 or later)
- Just
- CMake
- Ninja
- A C++ compiler:
- Windows: Visual Studio 2022 (x64)
- Linux: GCC (x64)
- Mac: Xcode and Xcode Command Line Tools (Apple Silicon)
Compilation and Testing
To build the solution locally, run the following command in the repository root:
just build
To run the tests, run the following command in the repository root:
just test
Contributing
If you find a bug or have a feature request, please open an issue on GitHub. If you'd like to contribute code, feel free to fork the repository and submit a pull request.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Ahwoo.BRUTAL.Core (>= 2026.10.1)
- Ahwoo.BRUTAL.Interop (>= 2026.10.1)
- Ahwoo.BRUTAL.Logging (>= 2026.10.2)
- Ahwoo.BRUTAL.Memory (>= 2026.10.1)
- Ahwoo.BRUTAL.Numerics (>= 2026.10.1)
- Ahwoo.BRUTAL.Strings (>= 2026.10.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Ahwoo.BRUTAL.Jolt:
| Package | Downloads |
|---|---|
|
com.IvanMurzak.Brutal.MCP.Jolt
Brutal-MCP extension for Ahwoo.BRUTAL.Jolt: exposes live Jolt physics to AI agents through RQL. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.10.2 | 852 | 10/15/2026 |
Rebuilds against Strings 2026.10.1 and the packages released on it. The previous 2026.10 release still pulled Brutal.T4 in through Strings 2026.10.0; this one no longer does.
No public API changes.
**Full Changelog:** [v2026.10.1...v2026.10.2](https://github.com/RocketWerkz/brutal.jolt/compare/v2026.10.1...v2026.10.2)