---
title: "Compare 3D physics snapshot differences in C#"
url: https://recursiveai.org/onegame/cookbook/describe-3d-physics-state-differences/
description: "Compare 3D physics snapshot differences in C# with OneGame: runnable .NET code, real output, and a downloadable example using the published physics package."
version: "2.0.0"
---

# Compare 3D physics snapshot differences in C#

**onegame** is a free, open-source game engine for .NET from Recursive AI. MIT or Apache-2.0, no editor required.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneGame.Physics) · [GitHub](https://github.com/recursive-ai-oss/onegame) · [Docs](https://recursiveai.org/onegame/docs/) · [Download example (.zip)](https://recursiveai.org/onegame/cookbook/describe-3d-physics-state-differences/describe-3d-physics-state-differences.zip)

Named snapshot differences identify which body field changed, instead of only reporting unequal hashes.

```shell
dotnet add package RecursiveAI.OneGame.Physics
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

`Fixed.One` is one in the engine’s deterministic fixed-point number type; `FVec3` is its three-dimensional vector type. The report also shows raw hexadecimal numeric encodings alongside the decoded values so you can inspect the exact representation.

```csharp
using OneGame.Core;
using OneGame.Physics;

var space = new PhysicsSpace3D();
var body = space.AddSphere(Fixed.One,
    new FVec3(0, 4, 0));
var expected = space.Snapshot();
var copy = space.Fork();
copy.SetVelocity(body, new FVec3(2, 0, 0));
Console.WriteLine(space.FindDifferences(copy));
Console.WriteLine(copy.DescribeDifferences(expected));
```

```text
1 differing fields:
bodies: body 0 (gen 1) linear velocity x: a=0 [0x00000000] b=2 [0x40000000]

1 differing fields:
bodies: body 0 (gen 1) linear velocity x: a=0 [0x00000000] b=2 [0x40000000]
```

Both reports identify the sphere’s changed X velocity. The first compares spaces; the second compares the saved snapshot with the modified space.

Unzip [the example](https://recursiveai.org/onegame/cookbook/describe-3d-physics-state-differences/describe-3d-physics-state-differences.zip), then `dotnet run`.

## Variations

Append this to see the diagnostic returned for a malformed snapshot.

```csharp
Console.WriteLine(copy.DescribeDifferences(
    new byte[] { 1, 2, 3 }));
```

```text
Physics diagnostic snapshot is invalid or incompatible.
```

## Related recipes

- [Encode a 3D physics snapshot delta in C#](https://recursiveai.org/onegame/cookbook/encode-3d-physics-snapshot-delta/)
- [Compress a 3D physics snapshot in C#](https://recursiveai.org/onegame/cookbook/compress-3d-physics-snapshot/)
- [Restore part of a 3D physics world in C#](https://recursiveai.org/onegame/cookbook/repair-3d-physics-region/)

## The short answer

Use `FindDifferences(otherSpace)` to compare two live `PhysicsSpace3D` instances. Use `DescribeDifferences(expectedSnapshot)` to compare the current space with retained snapshot bytes. Both return named text reports. The example changes a fork’s X velocity and shows the body slot, generation, and velocity component in each report.

## How do I compare 3D physics snapshot differences in C#?

Create a checkpoint with `Snapshot()` before the change you want to investigate. When a later state diverges, pass that checkpoint to `DescribeDifferences`. If you already hold both spaces in memory, call `FindDifferences` directly instead. The supplied program demonstrates both paths on the same controlled change, so you can see how they relate.

The output shows `body 0 (gen 1)` and `linear velocity x`. These values identify a body slot and generation in this example, not a gameplay entity name. A report that names a physics body still needs to be associated with your own gameplay object if your diagnostic tool displays entity-level context. The report does not create that association for you.

## How do I diagnose networked physics state differences?

Compare corresponding simulation checkpoints. A state captured before a tick and another captured after it can differ legitimately. First establish what tick and origin you intended to compare, then use the named report to narrow the investigation to specific fields. `Hash` is useful for noticing a mismatch, while the text report helps explain it.

The [physics integration contract](https://github.com/recursive-ai-oss/onegame/blob/60d5573da204de68cafd5896dc8d41b16c72ff9d/docs/interfaces/physics.md) describes these methods as replay and drift tooling. `Snapshot` and `DescribeDifferences` let tools retain and compare physics checkpoints without adding diagnostic payloads to engine recordings or replica messages. This recipe is therefore an in-process diagnostic, not a packet recorder or automatic desynchronization repair system.

For a replay investigation, retain the expected physics snapshot at the checkpoint you care about, then compare the replayed space at that same checkpoint. A mismatch report identifies state differences; it does not establish which earlier command or simulation decision caused them. Use it to narrow the search rather than treating the final changed field as the root cause.

## What happens if a physics diagnostic snapshot is invalid?

For malformed or incompatible snapshot bytes, `DescribeDifferences` returns `Physics diagnostic snapshot is invalid or incompatible.` The variation runs that path with a three-byte input. That message means comparison was unavailable, not that the states matched or that the current space was repaired.

There is a separate input-size check: bytes over 64 MiB throw `ArgumentOutOfRangeException` before comparison. `FindDifferences` requires a non-null other space. Keep these calling errors distinct from a valid report of differing fields.

The report is text for tooling, not a patch to apply to another space. If the next step is restoration, choose the appropriate full snapshot or compatible region repair API explicitly. Comparing snapshots does not advance the simulation, reconcile a prediction fork, or change the normal physics table serialization path.
