# How to Migrate from Older Jolt Physics Versions Using APIChanges Documentation

> Easily migrate Jolt Physics versions by using APIChanges documentation. Update symbols, re-cook assets, and implement double precision for a smooth transition.

- Repository: [Jorrit Rouwe/JoltPhysics](https://github.com/jrouwe/JoltPhysics)
- Tags: migration-guide
- Published: 2026-07-17

---

**Migrate Jolt Physics by consulting [`Docs/APIChanges.md`](https://github.com/jrouwe/JoltPhysics/blob/main/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`](https://github.com/jrouwe/JoltPhysics/blob/main/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/main/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`](https://github.com/jrouwe/JoltPhysics/blob/main/Jolt/Physics/Character/CharacterVirtual.h) |
| `CharacterVirtual::ContactKey` | `CharacterContactKey` | [`Jolt/Physics/Character/CharacterVirtual.h`](https://github.com/jrouwe/JoltPhysics/blob/main/Jolt/Physics/Character/CharacterVirtual.h) |
| `ObjectLayerPairFilter` | `ObjectVsBroadPhaseLayerFilter` | [`Jolt/Collision/ObjectLayer.h`](https://github.com/jrouwe/JoltPhysics/blob/main/Jolt/Collision/ObjectLayer.h) |
| `CollisionDispatch::sCastShapeVsShape` | `CollisionDispatch::sCastShapeVsShapeLocalSpace` | [`Jolt/Collision/CollisionDispatch.h`](https://github.com/jrouwe/JoltPhysics/blob/main/Jolt/Collision/CollisionDispatch.h) |

When updating `CharacterVirtual` listeners, replace the nested type with the standalone struct:

```cpp
// 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/main/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**

```cpp
// 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:

```cpp
// 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:

```cpp
// 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:

```cpp
// 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/main/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_ENABLED` and `CPP_RTTI_ENABLED` control these features

Update your CMake invocation to preserve previous behavior:

```bash
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:

```cpp
// 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:

```cpp
// 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:

```cpp
JPH::RayCastSettings settings;
// Old: settings.mBackFaceMode = JPH::EBackFaceMode::CollideWithBackFaces;
// New:
settings.SetBackFaceModeTriangles(JPH::EBackFaceMode::CollideWithBackFaces);
settings.SetBackFaceModeConvex(JPH::EBackFaceMode::IgnoreBackFaces);

```

## Summary

- **Consult [`Docs/APIChanges.md`](https://github.com/jrouwe/JoltPhysics/blob/main/Docs/APIChanges.md)** between 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`, and `VehicleConstraint` callbacks
- **Re-cook binary assets** rather than persisting `SaveBinaryState` blobs across versions
- **Adopt `RVec3`/`RMat44`** types to support double-precision builds
- **Use locking `BodyInterface`** methods 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/main/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`](https://github.com/jrouwe/JoltPhysics/blob/main/Jolt/Physics/Body/BodyInterface.h).