---
title: "Drive a 3D vehicle physics controller in C#"
url: https://recursiveai.org/onegame/cookbook/drive-3d-vehicle/
description: "Drive a 3D vehicle physics controller in C# with onegame: a runnable .NET 10 console example using the published physics package, with real output and a download."
version: "1.26.0"
---

# Drive a 3D vehicle physics controller 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/drive-3d-vehicle/drive-3d-vehicle.zip)

Attach a four-wheel suspension and drivetrain to a dynamic chassis, then supply throttle and steering each simulation tick.

```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.

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

var space = new PhysicsSpace3D();
space.AddBox(new FVec3(40, 1, 60),
    new FVec3(0, -1, 0),
    new BodyOptions3D { Kind = BodyKind.Static });
var chassis = space.AddBox(
    new FVec3(2, Fixed.FromRatio(1, 2), 4),
    new FVec3(0, 1, 0),
    new BodyOptions3D { Density = 100 });
var car = space.AddVehicle(chassis);
for (var tick = 0; tick < 120; tick++)
{
    space.Drive(car, Fixed.One,
        steering: Fixed.FromRatio(1, 10));
    space.Step();
}
Console.WriteLine($"Chassis position: {space.Position(chassis)}");
Console.WriteLine($"Wheels: {space.WheelCount(car)}");
Console.WriteLine($"Steering angle: {space.Wheel(car, 0).SteerAngle}");
Console.WriteLine($"Wheel 0 grounded: {space.Wheel(car, 0).Grounded}");
```

The floor, chassis and wheel setup are generated in code; no model or other input file is required.

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

```text
Chassis position: (0.279802709, 0.228901593, 4.208660767)
Wheels: 4
Steering angle: 0.050000001
Wheel 0 grounded: True
```

`Fixed` and `FVec3` are deterministic fixed-point scalar and 3D vector types: use `Fixed.FromInt(2)` or `new FVec3(2, 0, 0)` for integers, and convert a float with `Fixed.FromDouble(value)` outside sim code.

## Variations

**Drive with half throttle.** Replace `space.Drive(car, Fixed.One, steering: Fixed.FromRatio(1, 10));` in the program with:

```csharp
space.Drive(car, Fixed.FromRatio(1, 2),
    steering: Fixed.FromRatio(1, 10));
```

With that change, the program prints:

```text
Chassis position: (0.728411701, 0.22896192, 7.923016669)
Wheels: 4
Steering angle: 0.050000001
Wheel 0 grounded: True
```

## Related recipes

[Add 3D rigid body physics in C#](https://recursiveai.org/onegame/cookbook/3d-rigid-body-physics/) · [Move a 3D character controller in C#](https://recursiveai.org/onegame/cookbook/3d-character-controller/) · [Raycast a 3D physics world in C#](https://recursiveai.org/onegame/cookbook/raycast-3d-world/)

---

## The short answer

Create a dynamic box chassis, attach the standard car with `PhysicsSpace3D.AddVehicle`, and set its controls through `Drive` before stepping physics. The public wrapper supplies a standard four-wheel car, forward along +Z. It is not an arbitrary vehicle-definition editor.

The download creates a floor and a chassis, drives for 120 fixed ticks and reads the first wheel’s ground-contact state. It runs as a console simulation: it does not load a car model or open a game window. The printed chassis position comes from the simulation, not an animation.

## How do I make a 3D vehicle physics controller in C#?

Start with a dynamic chassis sized roughly `(2, 0.5, 4)`, as specified by the wrapper’s [documented setup](https://recursiveai.org/onegame/docs/physics/#3d-spaces). The example uses density 100. Add a floor that is large enough to support the car’s motion, then call `AddVehicle(chassis)`. Keep both references: the `BodyRef` identifies the chassis body and the `VehicleRef` identifies its suspension and drivetrain.

`Drive` takes throttle and steering from −1 to 1, plus brake and handbrake from 0 to 1. All four values are `Fixed`. The example sends full forward throttle and steering of 0.1, with both brakes left at zero. To feed real input into a game, convert actions to those control values in simulation code; don’t derive physics movement from a rendered mesh’s frame rate.

For a registered space, one world step advances the vehicle through the space’s post-entity system. Set controls before that step. For a standalone space, as in this console program, call `space.Step()` yourself. Don’t combine both stepping paths for a single simulation tick.

## How can I read a car’s wheel state in C#?

`WheelCount(car)` gives the number of attached wheels. `Wheel(car, index)` uses a zero-based index and returns center, radius, grounded state, contact point, suspension length, spin angle and steering angle. Spin and steering angles are in radians. The program reads index zero only after advancing the simulation.

Use that wheel state to position and rotate wheel art. Read the chassis pose separately with `space.Transform(chassis)` or its position and rotation methods. A wheel’s `Grounded` flag reports suspension contact; it is not a promise that all wheels touch ground or that the car is stationary. Inspect each wheel when the distinction matters.

Keep physics as the movement authority. In a networked game, mirror chassis pose and any required wheel view state into synced entity properties; the hidden physics table is not automatically copied to subscribed replicas. Rendering those properties should not issue throttle or steering changes.

Removing the vehicle removes its suspension and drivetrain while retaining its chassis body. Removing or recreating bodies is a separate lifetime decision. Avoid holding stale references after destruction; the wrapper checks references and throws `StaleBodyException` when they no longer identify a live object.
