Wheel API: RCCP 1 to RCCP 2
Read a wheel from code
Use RCCP_WheelCollider as the wheel facade, the public interface to the wheel system. The component owns its geometry, suspension and friction settings. New wheels do not need a Unity WheelCollider. Read the simulation results through this component.
Put this method in your component. Give the method the wheel facade that you want to examine.
using BoneCrackerGames;
void ReadWheel(RCCP_WheelCollider wheel) {
if (wheel == null) return;
float rpm = wheel.Rpm;
bool grounded = wheel.IsGrounded;
if (grounded && wheel.GetGroundHit(out UnityEngine.WheelHit hit))
UnityEngine.Debug.Log($"RPM: {rpm}, suspension force: {hit.force} N");
}
The solver publishes contact, spin, slip and force results after each solve. To read results in the same step in FixedUpdate, obey the execution order.
For usual driving, use the input API. For setup in the Inspector, use Wheels and tires.
Old wheel access and its replacement
In this table, wheel is an RCCP_WheelCollider. The first column shows old native access. Use the first column only for migration.
| Old native access | Facade member | RCCP 2 behavior |
|---|---|---|
wheel.WheelCollider or GetComponent<WheelCollider>() |
The members below | Removed. Use the RCCP properties below. |
.enabled |
IsLive |
Gets or sets solver participation without debris or repair. The component keeps this state separate from its enabled checkbox. |
.isGrounded |
IsGrounded |
Gets the published solver contact. The lowercase isGrounded field keeps the reading from the last FixedUpdate of the wheel. |
| Bounds center | HubPosition |
Gets the wheel center in world space, with suspension movement. |
.radius |
Radius |
Gets or sets the effective radius in local meters, before transform scale. Deflation changes this value. A write requests a settings refresh. |
| Wheel replacement radius | FittedRadius |
Gets or sets the fitted radius before deflation. A change keeps the current leak progress. Use this property to replace a wheel model. |
.rpm |
Rpm |
Gets the raw signed RPM, positive for forward rotation. WheelRPM is filtered and changes only while the wheel touches the ground. |
.steerAngle |
SteerAngleDeg |
Gets the wheel angle in degrees, positive to the right. After the solver step, this value includes the steering limit of the wheel. |
.suspensionSpring.spring |
SuspensionSpring |
Gets or sets the spring rate in N/m. Keeps the damper and rest position. |
.suspensionSpring.damper |
SuspensionDamper |
Gets or sets the damper rate in N·s/m. Keeps the spring and rest position. |
.suspensionSpring.targetPosition |
SuspensionTargetPosition |
Gets or sets the rest position from 0 to 1. Keeps the spring and damper. |
.suspensionDistance |
SuspensionDistance |
Gets or sets the suspension travel in meters. |
.forceAppPointDistance |
ForceAppPointDistance |
Gets or sets the force height in meters above the wheel bottom at rest. |
.motorTorque |
AppliedMotorTorque |
Gets the published drive torque in N·m. Use its setter only for resets, not to drive. |
.brakeTorque |
AppliedBrakeTorque |
Gets the published brake torque in N·m. Use its setter only for resets, not for brake commands. |
GetGroundHit(out WheelHit) |
GetGroundHit(out WheelHit hit) |
Returns the solver contact and a success flag. force is the suspension force. The slip fields contain compatibility values. |
ClosestPointOnBounds |
ClosestPointOnWheelBounds(Vector3 position) |
Gets the nearest point on the bounds from the solver hub, steering, radius and width. |
GetWorldPose |
HubPosition, SteerAngleDeg |
The facade has no public GetWorldPose. RCCP applies the visual pose to the wheel model internally. |
The suspension and force-height setters also request a solver settings refresh. To change the configuration, use these properties or SetWheelSettings.
Geometry, mass, springs and source friction curves give the solver configuration. When the settings revision of the facade changes, the solver refreshes its converted settings. The RCCP component keeps the source friction curves. The solver publishes the live force and slip outputs separately.
| Supported hook | What changes |
|---|---|
SetSuspension(float spring, float damper, float distance) |
Spring, damper and travel. Keeps the rest position and requests a settings refresh. |
SetSuspensionForces(float spring, float damper) |
Spring and damper. Keeps the travel and rest position and requests a settings refresh. |
SetFrictionCurvesForward(float extremumSlip, float extremumValue, float asymptoteSlip, float asymptoteValue) |
Forward source curve. Requests a settings refresh. |
SetFrictionCurvesSideways(float extremumSlip, float extremumValue, float asymptoteSlip, float asymptoteValue) |
Sideways source curve. Requests a settings refresh. |
frictionModifier delegate: void FrictionModifier(RCCP_WheelCollider wheel, ref WheelFrictionCurve forwardFriction, ref WheelFrictionCurve sidewaysFriction) |
Changes solver grip with only stiffness and extremumValue. Each axis uses stiffness * extremumValue / max(1e-4, authored extremumValue). Changes to extremumSlip, asymptoteSlip and asymptoteValue have no effect through this hook. The hook does not change the stored source curves in each step. |
A changed source curve can calculate its tire axis again. Unchanged curves keep the authored tire values. This rule also applies to curves that behavior presets write. See the preset workflow.
For a custom drivetrain, obey the accumulator pipeline. Usual driving uses throttle, brake and steering inputs.
New wheel readouts
These read-only properties give the solver results.
| Member | Meaning and units |
|---|---|
ContactPoint |
Contact position in world space. Zero when no contact exists. |
ContactNormal |
Solver contact normal in world space. Examine IsGrounded before you use contact data. |
ContactCollider |
Contact collider, or null when no contact exists. |
IsWallContact |
True for a solver wall contact. |
IsBottomed |
True when the suspension is at its compression limit. |
SuspensionForceN |
Suspension force along the suspension axis, in N. |
NormalLoadN |
Suspension force projected onto the contact normal, in N. |
SuspensionTravel01 |
Suspension compression: 0 at full extension, 1 at full compression. |
LongitudinalForceN |
Tire force along the longitudinal direction of the contact, in N. |
LateralForceN |
Tire force along the lateral direction of the contact, in N. |
SlipRatio |
Signed longitudinal slip ratio from the solver state, without units. |
SlipAngleDeg |
Signed lateral slip angle from the solver state, in degrees. |
NormalizedSlip |
Combined slip relative to the tire peaks, without units. A value of 1 is the combined peak. Values can be more than 1. |
Compatibility slip uses a different scale from the physical solver values above.
| Compatibility member | Meaning |
|---|---|
GetGroundHit slip fields |
Converted compatibility slip from the latest solver publication. Not the physical SlipRatio or SlipAngleDeg. |
wheelHit |
Contact that the wheel captures in its own FixedUpdate. Its slip fields use compatibility values. |
ForwardSlip, SidewaysSlip |
Filtered compatibility slip. During a replay, the recorded slip goes into these filters. |
TotalSlip |
Sum of the absolute filtered forward and sideways compatibility slip. |
After the next fixed step of a detached wheel, isGrounded and isSkidding are false, and wheelHit is empty.
The HubPosition of a detached wheel returns the position of the wheel object.
Wheel data from code
| Member | Meaning |
|---|---|
WheelData |
Gets a struct copy of the saved wheel data. A change to the copy does not change the wheel. |
WheelDataVersion |
Gets the saved version. Version 0 uses conversion in memory. |
CurrentWheelDataVersion |
Current saved format: 1. |
EffectiveWheelData |
Gets the effective data without a save. Converts version 0 in memory, or synchronizes changed tire curves in a copy of the saved data. |
SetWheelData(in RCCP_WheelData data) |
Saves the struct, sets version 1 and requests a solver settings refresh. Returns void. |
MigrateWheelData(bool force = false) |
Converts the source data and returns RCCP_ConversionFlags. Current data does not change unless force is true. |
To edit wheel data from code, get a copy from EffectiveWheelData. Change the copy, then give the copy to SetWheelData. In editor code, record Undo before you change authored data. If the wheel is in a prefab instance, record the prefab instance modifications.
CAUTION: Back up the wheel tuning before you call
MigrateWheelData(true). The call replaces the saved wheel data with a new conversion. The current wheel tuning can be lost.
For the editor upgrade procedure, see Old wheel data. For installation changes, see the upgrade guide.
Obsolete wheel settings
The wheel solver selects its substeps automatically. These old profile controls do not select solver substeps.
| Obsolete member | Compatibility behavior |
|---|---|
ConfigureSubsteps(float speedThreshold, int stepsBelowThreshold, int stepsAboveThreshold) |
Does nothing. |
RCCP_CarController.ReapplyWheelSubsteps() |
Removed. Remove calls to this method. |
RCCP_CarController.overrideWheelSubstepProfile |
Hidden compatibility field. |
RCCP_CarController.wheelSubstepProfile |
Hidden compatibility field. |
RCCP_WheelSubstepProfile |
Obsolete enum. Kept for serialized data and source compatibility. |
RCCP_Settings.BehaviorType.wheelSubstepProfile |
Hidden compatibility field. |
The Substeps setting of the damage solver (RCCP_DeformationSolver.substeps) is still active. That setting controls the dent simulation, not wheel profiles.
You can still call these deprecated wheel aliases:
| Deprecated alias | Replacement |
|---|---|
totalSlip |
TotalSlip |
wheelSlipAmountSideways |
SidewaysSlip |
wheelSlipAmountForward |
ForwardSlip |
negativeFeedbackIntensity |
Read engineBrakeTorqueNm in FixedUpdate after order -7 and before order 0. Then normalize the value for your haptic system. |
AddNegativeFeedback(float intensity) |
AddEngineBrakeTorque(float nmAtWheel), in N·m |
engineBrakeTorqueNm goes back to zero in the FixedUpdate of the wheel at order 0. Thus Update and LateUpdate read zero.
For haptics, read the value in a component with [DefaultExecutionOrder(-1)]. Keep that value for your later haptic update.
Reset wheel state
| Method | Scope |
|---|---|
wheel.ResetWheelState() |
Requests a reset for one wheel. |
car.WheelSolver.ResetAllWheels() |
Requests a reset for all wheels that are bound to that solver. |
RCCP_WheelSolver.ResetWheels(RCCP_CarController car) |
Calls the reset of the vehicle solver when the vehicle and the solver exist. |
A reset clears the spin, slip, contact and suspension memory before the next solve. The readouts do not change immediately when you request a reset.
Transport requests this reset, also for calls with resetVelocity: false. The replay director requests resets at playback start, live resume, direction changes, seeks and replay exit. Recorder playback also requests a reset when it moves the vehicle to the first recorded pose. Wheel spin and slip are not continuous across these operations.
See Transport and Instant replay for the entry points.