Damage System

RCC has a comprehensive damage system that handles mesh deformation, detachable body parts, wheel damage, and broken lights. This document explains how each piece works, how to configure it, and how to extend it for your own gameplay (e.g., destruction derbies, demolition modes, vehicular combat).

The damage system is embedded into RCC_CarControllerV4 rather than being a separate component — the field is damage of type RCC_Damage, marked [System.Serializable]. This is by design and is the source of one common confusion: you can't add a "Damage" component, because it's already part of the controller.

What Damage Affects

When a vehicle takes damage, four visible things change:

  1. Mesh deformation — vertices on the body push inward at collision contact points.
  2. Detachable parts — hoods, doors, bumpers can break off and become physics objects.
  3. Wheel damage — wheels can shift out of alignment or pop off entirely.
  4. Light damage — bulbs stop emitting light.

Each is configurable independently. You can enable all of them, or just the parts you want.

Enabling Damage

The top-level toggle is Use Damage in the RCC_Damage section of the Inspector. When off, no damage is processed (the vehicle is invincible). When on, damage accumulates from collisions.

By default this is on. To make a vehicle invincible (e.g., a tutorial mode or a "ghost car"), uncheck it.

Damage Sensitivity

Three fields control how easily the vehicle takes damage:

For a destruction derby game, increase Damage Multiplier to 2–3. For a casual driving game where minor scrapes shouldn't be visible, decrease it to 0.5.

Mesh Deformation

When the vehicle hits something hard enough, the affected body mesh has its vertices pushed inward from the collision point. The deformation depth scales with collision force.

How It Works

  1. On OnCollisionEnter, the controller reads each ContactPoint.
  2. For each contact, it builds a query: "find every vertex within deformation radius of this point."
  3. The query is served by an RCC_Octree — a spatial data structure built from the body mesh's vertices at startup. Octree queries are O(log N) instead of O(N), which matters for high-poly cars.
  4. Found vertices are displaced inward along the collision normal, scaled by force and damage multiplier.
  5. The mesh is marked dirty and Unity re-uploads it to the GPU.

Configuration

Field What It Does
Use Mesh Deformation Enable deformation.
Damage Radius How wide the deformation effect is per contact point.
Deformation Vertices Damage Multiplier Per-vertex displacement scalar.
Original Meshes Pose A pre-recorded list of rest positions for all body vertices. Recreated by clicking Recalculate Original Meshes.

"Recalculate Original Meshes"

If you change the vehicle's body mesh, you must regenerate the octree and the rest pose. Click Recalculate Original Meshes in the damage section. This is also necessary after attaching new detachable parts or changing the vehicle's hierarchy.

Mesh Deformation Caveats

Detachable Parts

A "detachable part" is a body part (hood, door, bumper, mirror) that can break off the vehicle on enough damage and become a separate physics object.

Setup

  1. Create the body part as a separate child GameObject under the vehicle root.
  2. Position it at the rest location.
  3. Add a Rigidbody component (keep it kinematic for now — the controller will un-kinematic it on break).
  4. Add a Collider (BoxCollider or MeshCollider).
  5. Add a ConfigurableJoint component connecting it to the vehicle's Rigidbody.
  6. Add an RCC_DetachablePart component.

The ConfigurableJoint is what holds the part to the body — when its breakForce is exceeded, Unity breaks the joint and the part becomes free.

RCC_DetachablePart Configuration

When the part breaks, the joint is removed, the rigidbody becomes non-kinematic, and gravity takes over.

Reattaching Parts on Repair

RCC.Repair(carController) re-parents broken parts back to the vehicle, restores their kinematic state, and recreates the joint. The part returns to its rest pose.

Built-in Detachable Part Examples

Open one of the demo vehicle prefabs (e.g., M3_E46_New.prefab) and look at its children. You'll find pre-configured detachable parts for the hood and bumpers. Use these as a template when adding your own.

Wheel Damage

Wheels can shift out of alignment or pop off entirely.

How It Works

When the wheel takes a strong sideways impact:

  1. The wheel's pivot transform shifts away from its rest position.
  2. The wheel collider remains at its original position (the visible wheel pivots away from the physics wheel).
  3. At high damage, the wheel is "popped off" — the wheel mesh is detached and falls as a rigidbody.

Configuration

Repair

RCC.Repair() resets each wheel transform to its rest pose and reattaches any popped-off wheels.

Light Damage

When the vehicle is damaged enough at the front (where headlights are) or back (brake/reverse lights), individual lights can be marked broken and stop emitting.

How It Works

The RCC_Damage system tracks each RCC_Light component on the vehicle and assigns it a damage score based on impacts in its vicinity. When the score exceeds a threshold, the light's intensity is forced to 0 and a small visible "broken bulb" effect plays (configured in the light's prefab — see 14 — Lights System).

Configuration

Repair

RCC.Repair() restores all lights to their original intensity.

Repairing

There are three ways to repair a vehicle:

1. Repair Now (Direct)

In code:

carController.damage.repairNow = true;

This triggers a full repair in the next FixedUpdate.

2. Public API

RCC.Repair(carController);   // Repair a specific vehicle.
RCC.Repair();                 // Repair the active player vehicle.

Both call the same code path.

3. Repair Station Prefab

Drop the RCC_RepairStation prefab into your scene. It's a trigger volume — when the player drives into it, the vehicle repairs automatically. You can edit the visual appearance of the trigger volume to look like a gas-station-style repair booth, a wrench icon on the ground, or whatever fits your art style.

The repair station's logic is in Scripts/Others/RCC_RepairStation.cs — a few dozen lines you can adapt for any custom repair logic (e.g., charge the player money on repair).

Damage Events

Subscribe to collision events through RCC_Events:

using UnityEngine;

public class DamageLogger : MonoBehaviour {
    void OnEnable()  { RCC_Events.OnRCCPlayerCollision += HandleCollision; }
    void OnDisable() { RCC_Events.OnRCCPlayerCollision -= HandleCollision; }

    void HandleCollision(RCC_CarControllerV4 vehicle, Collision collision) {
        float impactSpeed = collision.relativeVelocity.magnitude;
        Debug.Log($"Crashed at {impactSpeed:F1} m/s into {collision.gameObject.name}");
        // Subtract score, play sound, etc.
    }
}

The event fires inside RCC_CarControllerV4.OnCollisionEnter. The collision parameter is Unity's standard Collision struct, so you have access to contact points, relative velocity, the other collider, etc.

Damage State Queries

In your own game code, you may want to know whether the player has taken too much damage (e.g., to fail a mission, or to disable the vehicle until repaired):

RCC_CarControllerV4 vehicle = RCC_SceneManager.Instance.activePlayerVehicle;
if (vehicle != null) {
    float currentDamage = vehicle.damage.totalDamage;
    float maxDamage = vehicle.damage.maxDamage;
    float damagePercent = currentDamage / maxDamage;
    if (damagePercent >= 1.0f) {
        // Vehicle is fully damaged.
    }
}

(Field names may vary slightly — check RCC_Damage.cs for the actual field your version exposes.)

Tuning Damage Feel

The damage system has many knobs. Here are the most useful tuning levers in order of impact:

  1. Damage Multiplier — overall sensitivity. Adjust this first.
  2. Damage Radius — how local each impact's deformation is. Larger = wider dents.
  3. Detachable Part Break Force — when parts come off. Lower for action games, higher for sim.
  4. Wheel Damage Multiplier — how easily wheels go out of alignment.
  5. Light Damage Multiplier — how easily lights break.

For a destruction derby game, set:

For a casual driving game, set:

For a simulator, leave defaults — they're tuned for realistic feel.

Performance Considerations

Damage processing has two costs:

  1. Octree build at startup — proportional to total vehicle vertices. ~10 ms for a 10k-vertex car. One-time only.
  2. Per-collision deformation — proportional to vertices within damage radius. Usually negligible (<1 ms).

Detachable parts and broken wheels create runtime rigidbodies — Unity-default physics objects. A vehicle with 5 broken parts is roughly equivalent in cost to a vehicle with 5 child rigidbodies, which is fine on desktop and acceptable on mobile.

If you have many damaged vehicles in a scene (e.g., a wrecking yard environment), consider disabling damage on background vehicles and only enabling it on the active player + AI opponents.

Common Damage Issues

"Mesh deformation doesn't work"

Most common: the body mesh is a SkinnedMeshRenderer instead of a MeshRenderer. Skinned meshes can't be deformed by RCC. Convert the body to a static mesh (right-click the mesh asset → Re-Import with skinning disabled).

Second most common: Recalculate Original Meshes hasn't been clicked since the prefab was modified. Click it and try again.

"Detachable parts fall off too easily / too hard"

Adjust Break Force on each ConfigurableJoint. Test at intentional impact speeds (e.g., drive into a wall at 30 km/h) until breakaway threshold feels right.

"The wheels look broken after a small bump"

Wheel Damage Multiplier is too high. Lower it.

"I clicked Repair but the parts didn't come back"

The detachable parts need to be children of the vehicle when Repair is called. If a part has been completely destroyed (e.g., its GameObject was destroyed by an explosion in your own code), it can't be restored. The repair only resets parts that are still in the scene.

Next Steps