> For the complete documentation index, see [llms.txt](https://malbersanimations.gitbook.io/animal-controller/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://malbersanimations.gitbook.io/animal-controller/riding/hap-riding-system/wagons.md).

# Wagons

Last updated AC v1.5.3

## Overview

A **Wagon** is a physics vehicle towed by one or two Animals. The Animals are driven by the **Animal Controller** exactly as they always are — you mount, you press forward, the horse walks — and the wagon follows on wheel colliders, hitched to the Animal by a Configurable Joint.

Two components make it work:

* **Pulling Horses** sits on the Animal (or on a parent grouping a pair) and turns them around the wagon's front axle instead of around their own pivot.
* **Wagon Controller** sits on the wagon and owns the wheels, the steering measurement, the brakes, the physics tuning of the whole chain, and the rolling and creak sounds.

{% hint style="info" %}
Both components have a **Setup Check** panel at the bottom of their Inspector. It measures your actual rig — suspension against the weight each wheel carries, damping against critical, joint configuration, layers, audio — and offers one-click fixes. If a wagon misbehaves, read that panel before changing anything by hand.
{% endhint %}

***

## Requirements

* An Animal with the **Animal Controller**, its Animator Update Mode on **Fixed**, and a **dynamic** (non-kinematic) Rigidbody.
* A wagon hierarchy with two Rigidbodies — the front assembly and the body — joined by a Configurable Joint.
* A Configurable Joint on the wagon front, connected to the Animal's Rigidbody.
* Four Wheel Colliders, and four meshes for them to drive.

The ready-made rigs are in `Horse AnimSet Pro/4 - Prefabs/Wagon`:

| Prefab                           | Animals                 |
| -------------------------------- | ----------------------- |
| `Single Wagon Horse`             | one horse               |
| `Double Wagon Horses`            | two horses side by side |
| `Single/Double Wagon ... Mobile` | mobile variants         |

The demo scene is `Horse AnimSet Pro/1 - Demos/7 - HAP Wagon`.

***

## How it works

The rig is three rigid bodies in a chain. The Animal pulls the front assembly, and the front assembly pulls the body.

```
Main Horse Carriage   (Rigidbody, dynamic)   ← Animal Controller drives this
│   PullingHorses ── turns the Animal around the wagon's front axle
│
└─ ConfigurableJoint ── linear axes Locked, hitch
   │
   Western Wagon      (Rigidbody)             ← the front assembly
   │   WagonController
   ├── FrontStear  ── front axle + Front Wheel Left/Right
   │
   └─ ConfigurableJoint ── the wagon's articulation
      │
      Body            (Rigidbody)             ← the wagon body
      └── Wheels Collider ── Back Wheel Left/Right, mount points, passenger seat
```

**Steering.** The Animal does not steer the wagon with a steering wheel. `PullingHorses` rotates the Animal around a pivot behind it (`Rotation Offset`, roughly the front axle), and the hitch drags the front assembly around with it. `WagonController` then measures the angle between the body and the front assembly and reports it back, so the Animal can be stopped from folding the wagon past its articulation limit.

**Pairs.** With two Animals, only the **Main Animal** is simulated. The **Second Animal** is placed each frame at a fixed offset from the first, and its movement input is mirrored so both play the same gait.

**Sounds.** While the wagon moves, a wheel rolling loop and a wood creak loop play from a **Wagon Sounds** child that the controller creates at runtime. Their volume and pitch follow the wagon's own speed through curves, the creak spikes when the body pitches or rolls over a bump, and the rolling loop swaps per ground surface with a crossfade. The wagon speed comes from the wagon Rigidbody, not from the Animal, so the sounds keep rolling while it coasts and stop once it actually rests. See [Audio](#audio).

***

## Setting up the physics

Most wagon problems are one of the values below. The Setup Check computes all of them for your rig; this section explains what it is checking and why.

### Suspension springs

A Wheel Collider's spring has to carry the weight resting on it. The force it can produce is `spring × suspensionDistance × targetPosition`, so a large spring with a tiny travel is still a bottomed-out suspension.

```
required spring = sprungMass × 9.81 / (suspensionDistance × targetPosition)
```

Where `sprungMass` is the mass of the Rigidbody that wheel belongs to, divided by the number of wheels on that same Rigidbody. Note that the front and rear wheels usually belong to **different** Rigidbodies, so they are sized separately.

{% hint style="warning" %}
A bottomed-out suspension does not look soft — it looks like the wagon scrapes, hops and catches on flat ground, because the wheel has no travel left and every bump goes straight into the body.
{% endhint %}

### Damping

A spring with too little damping oscillates and never settles. Critical damping is `2 × √(spring × sprungMass)`; aim for **20% to 80%** of it. Far below that and the wagon bounces; far above and the suspension feels welded.

### Wheel mass

Wheel Collider mass is the wheel itself, not the load. A wheel heavier than about half of what it carries dominates the suspension response and makes the wagon feel unstable. Keep it well under the sprung mass.

### Solver iterations

The three bodies are chained by joints with **every linear axis Locked**. That chain cannot converge on Unity's default solver iteration count, and the joints visibly stretch. `Wagon Controller` raises the iteration count on the wagon's bodies at runtime instead of forcing a project-wide setting.

### Horse Mass Scale

The Animal Controller moves the Animal by assigning `Rigidbody.linearVelocity` directly every physics step — in translation the Animal behaves as if it were kinematic. The joint does not know that. Left alone it treats the Animal as an ordinary dynamic body, splits every correction between Animal and wagon by mass, and drags the Animal backwards each step.

At speed the momentum carries through it. At walking pace it does not, and **the Animal runs on the spot**. `Horse Mass Scale` tells the solver to satisfy the hitch by moving the wagon instead.

***

## Wagon Controller

\[Insert Image - Wagon Controller Inspector, Horse tab]

### Horse

#### Horse Rigid Body

Rigidbody of the Animal that pulls the wagon. The **Pulling Horses** component is found from here, searching this GameObject and its parents.

#### Horse Joint

The Configurable Joint that hitches the wagon to the Animal. Its Connected Body is assigned on Start if it is empty, but you should set it in the prefab so the joint is not welded to the world for the first frames.

#### Max Turn Angle

How far the front assembly may fold relative to the body before the Animal is stopped from turning further. Requires **Use Wagon Turn Limit** on the Pulling Horses component.

#### Body Collider / Stear Collider

The two Transforms whose forward directions are compared to measure the steering angle. `Body Collider` is on the wagon body, `Stear Collider` on the front assembly.

### Wagon

#### Wheel Colliders / Wheel Meshes

The Wheel Colliders, and the meshes they drive. **The two arrays are matched by index**, so they must be the same length and in the same order.

The meshes keep the orientation they were authored with — a wheel modelled on its side stays on its side — because the collider's pose is combined with the mesh's own rotation rather than replacing it.

#### Body / Stear Mesh

The wagon body and front assembly meshes. They are re-parented to their colliders on Start so they follow the simulated parts.

#### Center Of Mass

Optional Transform overriding the wagon's centre of mass. Left empty, the wagon uses the centre implied by its colliders — on a wagon whose only colliders sit at the axles that is usually too high and too far forward. Assign a low, central Transform if the wagon feels tippy.

#### On Moving Changed

Unity Event `(bool)` under the **Events** foldout. Invoked once when the wagon starts moving (`true`) and once when it comes to rest (`false`). See [Events](#events).

### Physics

#### Solver Iterations / Solver Velocity Iterations

Solver iterations applied to the wagon's Rigidbodies at Start. See [Solver iterations](#solver-iterations).

#### Horse Mass Scale

How many times heavier the hitch treats the Animal than its real mass. `1` disables it. See [Horse Mass Scale](#horse-mass-scale).

#### Ignore Pulling Animals

Ignores collisions between the wagon's colliders and the Animals pulling it.

{% hint style="info" %}
**Enable Collision** on a joint only covers the two bodies that joint connects. The Animal is jointed to the wagon **front**, never directly to the wagon **body**, so that pair still collides and can jam on tight turns. This option suppresses it per collider, leaving the wagon solid to everyone else.
{% endhint %}

#### Brake Torque / Brake Speed

The **parking** brake. No braking is applied while the wagon is rolling — it coasts to a stop like a real wagon. Once it drops below `Brake Speed`, `Brake Torque` is applied to hold it, which is what keeps it from creeping down a slope.

`Brake Speed` also decides when the wagon counts as **moving** for the sounds and the On Moving Changed event. The wagon starts moving above `Brake Speed` and counts as stopped again under **half** of it, so the rebound of a hard stop does not flicker the brake, the loops or the event.

`Brake Torque` must hold the wagon's weight on the steepest slope you expect. Braking while still moving is what locks the wheels dead the moment you release the movement input.

### Audio

\[Insert Image - Wagon Controller Inspector, Audio tab]

The loops are played from three Audio Sources created at runtime under a **Wagon Sounds** child, placed at the Center Of Mass. Two of them carry the rolling loop so a surface change can crossfade instead of restarting, the third carries the creak. Silent loops are stopped, so a resting wagon holds no audio voices.

{% hint style="info" %}
Rolling and creak sounds are **loops**. An Audio Clip is looped by the Audio Source. An **Audio Random Container** has to be authored with *Trigger* set to **Automatic** and *Loop* set to **Infinite**, because the Audio Source loop flag is ignored for containers.
{% endhint %}

#### Play Sounds

Enables the rolling and creak loops. When it is off no Audio Source is created.

#### Wheel Surfaces

Optional **Step Surfaces** asset with one rolling loop per ground surface. The `Sound` of each entry is the loop for that surface and the asset `Default Sound` covers unmatched ground. The ground under the wheels is identified the same way the [**Steps Manager**](/animal-controller/utilities/steps-manager.md) identifies footsteps: by a **Surface Tag** component on the ground, by the dominant **Terrain Layer** texture, or by the main texture of the mesh material.

{% hint style="warning" %}
The ground is whatever **Collider** the Wheel Colliders are resting on. A Surface Tag on an object with no Collider is never seen — the wheels roll on whatever is underneath it, usually the Terrain. Use a **separate** Step Surfaces asset for the wheels: the footstep asset holds one-shot step sounds, not loops.
{% endhint %}

#### Rolling Sound

Rolling loop used when no Wheel Surfaces asset is assigned, or the asset has no Default Sound.

#### Rolling Volume / Rolling Pitch

Volume and pitch of the rolling loop over the normalised speed (`0` = stopped, `1` = Max Speed).

#### Creak Sound

Wood creak and rattle loop.

#### Creak Volume / Creak Pitch

Volume and pitch of the creak loop over the normalised speed.

#### Bump Sensitivity

Extra creak volume per rad/s of body pitch and roll rate, so bumps and curbs make the wagon rattle. `0` disables it.

#### Bump Decay

How fast the bump boost fades, per second.

#### Max Speed

Speed, in m/s, that maps to `1` on every volume and pitch curve. Set it to the top speed of the Animal pulling the wagon — the HAP Horse gallops at about 13 m/s.

#### Fade Time

Seconds used to fade the loops in and out, and to crossfade the rolling loop between two surfaces.

#### Spatial Blend / Min Distance / Max Distance / Mixer Group

Standard Audio Source mixing values applied to the three sources when they are created.

#### Surface Check Interval

Physics steps between ground surface checks under the wheels. Raise it on mobile; the Mobile prefabs ship with a higher value.

### Debug

Draws the wagon's colliders and wheels in the Scene View. In Play Mode the Audio tab also shows a live readout: the wagon speed, the moving state, the surface entry in use, and the **Ground** collider the wheels are resting on with its layer. When the surface reads Default while you expect a match, the Ground line tells you what the wheels are really touching.

### Events

#### On Moving Changed `(bool)`

Invoked once when the wagon speed rises above **Brake Speed** (`true`) and once when it comes to rest (`false`). Use it to start or stop your own effects, or to react to the wagon stopping on a slope.

### Public Properties

| Property         | Type          | Description                                                                         |
| ---------------- | ------------- | ----------------------------------------------------------------------------------- |
| `Speed`          | `float`       | Speed of the wagon in m/s, updated every physics step.                              |
| `IsMoving`       | `bool`        | True while the wagon moves faster than Brake Speed (with the stop hysteresis).      |
| `CurrentSurface` | `StepSurface` | Surface entry the wheels are rolling on. Null on unmatched ground or with no asset. |
| `CurrentGround`  | `Collider`    | Ground collider under the first grounded wheel at the last surface check.           |

***

## Pulling Horses

\[Insert Image - Pulling Horses Inspector]

### Animals

#### Main Animal

The Animal that steers. Its Rigidbody must be **dynamic** — the Animal Controller moves it by writing velocity, which a kinematic body ignores. The component disables itself if this is empty.

#### Second Animal

Optional Animal yoked alongside the first. Leave it empty for a single-animal rig.

{% hint style="warning" %}
A paired Second Animal should have a **Kinematic** Rigidbody. It is positioned by transform every frame, and a dynamic Rigidbody fights those writes.
{% endhint %}

The side-by-side offset is captured on Start from the positions you author, so place the pair where they should stand before entering Play Mode.

### Turning

#### Rotation Offset

The local point the Animals turn around, usually near the wagon's front axle — a negative Z, behind the Animal.

Left at zero, the Animals pivot around their own root and the wagon swings wide and fights the hitch on every turn.

#### Use Wagon Turn Limit

Stops the Animals turning further once the Wagon Controller reports the steer is at its **Max Turn Angle**. The limit only blocks the direction that would fold the wagon further; unwinding is always allowed.

With no Wagon Controller driving this component the flag has no effect and turning works normally.

### Debug

Draws the rotation pivot in the Scene View.

***

## Troubleshooting

#### The Animal walks on the spot and the wagon does not move

`Horse Mass Scale` is at 1. The hitch is fighting the Animal's velocity assignment. See [Horse Mass Scale](#horse-mass-scale).

#### The wheels stop dead the moment I release the movement key

`Brake Speed` is too high, so the parking brake engages while the wagon is still rolling. The wagon should coast and only brake once stopped.

#### The wagon scrapes, hops or catches on flat ground

The suspension is bottomed out. Check the spring against the weight each wheel carries — see [Suspension springs](#suspension-springs).

#### The second Animal jitters while moving

Its Rigidbody is probably dynamic instead of kinematic. See [Second Animal](#second-animal).

#### The wagon makes no sound

`Play Sounds` is off, or no loop is assigned — the Setup Check says which. If a loop is assigned but plays once and stops, it is not authored as a loop: an Audio Random Container needs *Trigger* **Automatic** and *Loop* **Infinite**. If the loop plays at the wrong loudness everywhere, `Max Speed` is far from the Animal's real top speed and the curves saturate.

#### The rolling sound never changes with the ground

Read the **Ground** line of the Audio tab readout first. If it names the Terrain while you are driving over a tagged object, that object has **no Collider** and the wheels are rolling on the Terrain under it — add a Collider to it. If the Ground is right but the surface still reads Default, the Wheel Surfaces entries do not match it: an entry matches by its **Surface ID** (a Surface Tag component on the ground) or by its **Textures** (Terrain Layer diffuse or mesh material main texture). A terrain with a single layer and no Surface Tags resolves to the Default Sound everywhere. Note that the ground classification is cached per Collider on first contact, so a Surface Tag added during Play Mode is only seen after the next Play.

#### The camera or the wagon looks choppy

The camera and everything it follows have to be sampled on the same clock. The Animal Controller runs its Animator on **Fixed** update and moves characters on the physics step, so the whole rig should match it:

* Cinemachine Brain **Update Method** and **Blend Update Method** on **Fixed Update**
* Rigidbody **Interpolation** on **None**, both on the characters and on the wagon bodies

Mixing the two — an interpolated body under a Fixed Update Brain, or the reverse — samples a pose at a different moment than the one being drawn, and that reads as jitter. Smart Update guesses per target and is not a reliable middle ground.

#### The Animals fold the wagon past its limit

**Use Wagon Turn Limit** is off, or no Wagon Controller resolves back to this Pulling Horses component. On a two-Animal rig the component often sits on the parent that groups the pair — the Wagon Controller searches the Animal's parents to find it.
