How to Migrate from Older Jolt Physics Versions Using APIChanges Documentation
Migrate Jolt Physics by consulting Docs/APIChanges.md for symbol renames and signature changes, re-cooking binary assets to handle SBS (Serialization Breaking Changes), and updating Vec3/Mat44 to RVec3/RMat44 when enabling double precision.
The jrouwe/JoltPhysics repository evolves rapidly, with most releases maintaining backward compatibility but occasional updates introducing breaking API changes. When upgrading your project from an older tag to the current master branch, the Docs/APIChanges.md file serves as the authoritative source for migration steps. This guide walks you through the systematic process of identifying version gaps, applying concrete code fixes, and validating your build against the latest physics engine features.
Locate Breaking Changes in APIChanges.md
Before modifying any code, identify the version span you are crossing. Locate your current tag and target tag, then read the corresponding sections in [Docs/APIChanges.md](https://github.com/jrouwe/JoltPhysics/blob/master/Docs/APIChanges.md). Breaking changes are marked with *SBS* (Serialization Breaking Changes) or noted explicitly as API modifications.
Search your codebase for the affected symbols listed in the changelog. The document organizes changes chronologically, making it straightforward to step through each version incrementally rather than jumping directly to the latest commit.
Renamed and Relocated Types
Type renames are the most common migration task. Update your headers and source files to match the new locations and names exactly as documented.
| Old Name | New Name | Source File |
|---|---|---|
CharacterVirtual::Contact |
CharacterContact |
Jolt/Physics/Character/CharacterVirtual.h |
CharacterVirtual::ContactKey |
CharacterContactKey |
Jolt/Physics/Character/CharacterVirtual.h |
ObjectLayerPairFilter |
ObjectVsBroadPhaseLayerFilter |
Jolt/Collision/ObjectLayer.h |
CollisionDispatch::sCastShapeVsShape |
CollisionDispatch::sCastShapeVsShapeLocalSpace |
Jolt/Collision/CollisionDispatch.h |
When updating CharacterVirtual listeners, replace the nested type with the standalone struct:
// Old API (pre-v5.2)
void OnContactAdded(const JPH::CharacterVirtual::Contact &inContact, ...);
// New API (v5.2+)
void OnContactAdded(const JPH::CharacterContact &inContact, ...) override;
The ShapeFilter signature also changed to receive explicit shape pointers and sub-shape IDs rather than references, requiring updates in [Jolt/Collision/NarrowPhaseQuery.h](https://github.com/jrouwe/JoltPhysics/blob/master/Jolt/Collision/NarrowPhaseQuery.h).
Function Signature Updates
Several core functions changed their parameters to improve thread safety or add functionality. You must update your implementations to match these new signatures.
PhysicsStepListener::OnStep
// Old signature
void OnStep(float delta_time, PhysicsSystem &system);
// New signature (v5.1+)
void OnStep(PhysicsStepListenerContext const &inContext);
// Access delta time via inContext.mDeltaTime
VehicleConstraint::CombineFunction
The callback now receives a Wheel * parameter and wheel index, requiring you to forward these values to your existing logic.
Shape::CollideSoftBodyVertices
Changed from accepting an Array<SoftBodyVertex> to a CollideSoftBodyVertexIterator object. Replace array loops with iterator-based traversal as noted in the 20240922 changelog entry.
RayCastSettings BackFace Mode
The single mBackFaceMode enum split into mBackFaceModeTriangles and mBackFaceModeConvex. Use SetBackFaceModeTriangles() and SetBackFaceModeConvex() to configure these independently.
Binary Serialization Changes (SBS)
Binary state formats change frequently (marked *SBS*). Height fields, soft bodies, and rigid body serialization formats are not stable across major versions.
Never persist Jolt binary blobs across version jumps. Instead, store raw asset data (mesh vertices, height-field grids) and re-cook at runtime or during your asset pipeline:
// Re-cook height field after format change (20260307 entry)
JPH::HeightFieldShapeSettings settings;
settings.mSamples = LoadHeightSamplesFromYourFormat();
settings.mBitsPerSample = 16; // Explicitly set new required field
auto result = settings.Create();
if (result.IsValid())
SaveBinaryState(result.Get(), "MyHeightField_v2.bin");
If you must read old blobs, implement the binary compatibility shims described in the specific changelog entries (e.g., for HeightFieldShapeSettings::mBitsPerSample changes).
Double-Precision Type Migration
Starting with v5.2.0, public APIs switched from Vec3/Mat44 to RVec3/RMat44 to support double-precision builds. When JPH_DOUBLE_PRECISION is enabled, these types map to 64-bit precision; in single-precision mode, they remain 32-bit.
Update your code to use the real-number types:
// Before v5.2
JPH::Vec3 position = JPH::Vec3(0, 10, 0);
// After v5.2 (works in both precision modes)
JPH::RVec3 position = JPH::RVec3(0, 10, 0);
Replace all Vec3 and Mat44 usages with RVec3 and RMat44, or create a compatibility header with using directives if maintaining dual-precision support.
Thread-Safety and Locking Adjustments
The distinction between locking and non-locking BodyInterface methods is now enforced with assertions. When JPH_ENABLE_ASSERTS is defined, calling non-locking methods from multiple threads triggers warnings.
Replace unsafe calls with their locking counterparts:
// Potentially unsafe (non-locking)
bodyInterface.SetPosition(bodyID, position);
// Thread-safe alternative
bodyInterface.SetPosition(bodyID, position, EActivation::Activate);
// Or use BodyInterfaceLocking wrapper
Review [Jolt/Physics/Body/BodyInterface.h](https://github.com/jrouwe/JoltPhysics/blob/master/Jolt/Physics/Body/BodyInterface.h) to identify which methods require explicit locking.
CMake Build System Updates
Recent versions added options for graphics back-ends and exception handling:
- Graphics APIs:
JPH_USE_DX12,JPH_USE_VK,JPH_USE_MTL(Metal) are now optional CMake flags - Exceptions/RTTI:
CPP_EXCEPTIONS_ENABLEDandCPP_RTTI_ENABLEDcontrol these features
Update your CMake invocation to preserve previous behavior:
cmake -DJPH_USE_VK=ON -DCPP_EXCEPTIONS_ENABLED=ON ...
Practical Migration Examples
Updating Custom ShapeFilter Implementations
The ShapeFilter signature changed in the 20230316 update to receive a pointer and sub-shape ID:
// Old implementation
bool MyFilter::ShouldCollide(const JPH::Shape &inShape) const {
return inShape.GetSubShapeUserData() == mWanted;
}
// New implementation (Docs/APIChanges.md -> 20230316)
bool MyFilter::ShouldCollide(const JPH::Shape *inShape,
JPH::SubShapeID inSubShapeID) const {
return inShape && inShape->GetSubShapeUserData() == mWanted;
}
Handling Body Creation Serialization Flags
BodyCreationSettings::mAllowDynamicOrKinematic exists in both old and new versions, but the binary serialization flags changed. Force a re-cook of body settings when loading old saves:
// After loading old binary state, verify and update flags
if (oldVersion < 5.2f) {
settings.mAllowDynamicOrKinematic = true; // Update explicit flag
}
Ray Cast Settings Adjustment
Update ray cast initialization to handle the split back-face mode settings:
JPH::RayCastSettings settings;
// Old: settings.mBackFaceMode = JPH::EBackFaceMode::CollideWithBackFaces;
// New:
settings.SetBackFaceModeTriangles(JPH::EBackFaceMode::CollideWithBackFaces);
settings.SetBackFaceModeConvex(JPH::EBackFaceMode::IgnoreBackFaces);
Summary
- Consult
Docs/APIChanges.mdbetween your current and target versions to identify all breaking changes - Rename types exactly as listed (e.g.,
CharacterVirtual::Contact→CharacterContact) - Update function signatures for
PhysicsStepListener,ShapeFilter, andVehicleConstraintcallbacks - Re-cook binary assets rather than persisting
SaveBinaryStateblobs across versions - Adopt
RVec3/RMat44types to support double-precision builds - Use locking
BodyInterfacemethods when accessing physics from multiple threads - Adjust CMake flags for graphics back-ends and exception handling to match your project requirements
Frequently Asked Questions
Where is the official Jolt Physics migration documentation?
The official migration documentation resides in [Docs/APIChanges.md](https://github.com/jrouwe/JoltPhysics/blob/master/Docs/APIChanges.md) in the root of the jrouwe/JoltPhysics repository. This file contains a chronological list of all breaking API changes and serialization format updates, each marked with the date and version range where the change occurred.
Can I load binary physics saves from older Jolt versions?
No, binary physics saves are not backward compatible across versions marked with *SBS* (Serialization Breaking Changes). You must store your original asset data (meshes, height fields, body parameters) and re-cook the physics shapes using the new Jolt version's creation functions rather than loading old binary blobs.
What is the difference between Vec3 and RVec3 in Jolt Physics?
Vec3 is the traditional 32-bit floating-point vector type, while RVec3 is the "real" number vector that maps to Vec3 in single-precision builds and Double3 when JPH_DOUBLE_PRECISION is enabled. Starting with v5.2.0, public APIs use RVec3 and RMat44 to support both precision modes transparently.
How do I fix threading errors after upgrading Jolt Physics?
Enable JPH_ENABLE_ASSERTS in your build to catch thread-safety violations. Replace non-locking BodyInterface methods (like SetPosition or SetRotation) with their locking equivalents, or use the BodyInterfaceLocking wrapper class. Ensure all physics system access from multiple threads uses the appropriate locking mechanisms documented in Jolt/Physics/Body/BodyInterface.h.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →