Mobile Controls

Table of Contents

Realistic Car Controller Pro includes a complete mobile input system with four controller types to choose from. The system is driven by the RCCP_MobileInputs component, which reads values from on-screen UI elements and feeds them into the main input pipeline. All mobile controller settings live inside RCCP_Settings, and the visual controls are part of the RCCP UI Canvas prefab.


Overview

RCCP provides four mobile controller types:

ControllerSteering MethodUI Elements Shown
TouchScreenLeft/Right buttonsSteer Left, Steer Right, Throttle, Brake, Handbrake, NOS
GyroDevice tilt (accelerometer)Throttle, Brake, Handbrake, NOS (no steering buttons)
SteeringWheelRotatable on-screen wheelSteering Wheel, Throttle, Brake, Handbrake, NOS
JoystickDraggable analog stickJoystick, Throttle, Brake, Handbrake, NOS

The NOS button only appears when the active player vehicle has a NOS addon component attached.


Enabling Mobile Controls

  1. Open RCCP Settings: Tools > BoneCracker Games > Realistic Car Controller Pro > Settings
  2. In the Mobile Input section, enable mobileControllerEnabled (set to true)
  3. Select the desired controller type from the mobileController dropdown

When mobileControllerEnabled is false, the mobile canvas is automatically hidden regardless of platform. When true, the canvas activates and shows the appropriate UI elements for the selected controller type.

Settings Reference

FieldTypeDefaultDescription
mobileControllerEnabledboolfalseMaster toggle for mobile controls
mobileControllerenumTouchScreenActive controller type
gyroSensitivityfloat2.5Accelerometer sensitivity multiplier (Gyro mode only)

Controller Types

TouchScreen

The simplest mobile input mode. Six on-screen buttons handle all vehicle controls:

Steering is computed as -left.input + right.input, giving a final range of -1 (full left) to 1 (full right).

Sensitivity and Gravity

Each RCCP_UIController button has two tuning parameters:

ParameterDefaultWhat It Does
sensitivity5.0How fast the input value ramps up toward 1 when the button is held. Higher values produce snappier response.
gravity5.0How fast the input value returns to 0 when the button is released. Higher values make the input drop off faster.

Both values are multiplied by Time.deltaTime each frame, so the actual ramp speed is framerate-independent. The input is clamped between 0 and 1.

Gyro (Accelerometer)

In Gyro mode, the device's built-in accelerometer controls steering. RCCP uses Unity's New Input System accelerometer (UnityEngine.InputSystem.Accelerometer.current) to read the device tilt.

Tuning tip: Start with the default gyroSensitivity of 2.5. Increase it if steering feels too sluggish on tilt, decrease it if small movements cause oversteering.

Steering Wheel

An on-screen rotatable steering wheel rendered by RCCP_UI_SteeringWheelController. The player drags the wheel image to rotate it, and the rotation angle is converted to a normalized steering value between -1 and 1.

ParameterDefaultDescription
steeringWheelMaximumsteerAngle270Maximum rotation angle in degrees (both directions). The wheel can rotate from -270 to +270.
steeringWheelResetPosSpeed20How fast the wheel auto-centers when released. Uses Mathf.MoveTowards scaled by Time.deltaTime * 100.
steeringWheelCenterDeadZoneRadius5Pixel radius around the wheel center where touch input is ignored. Prevents jitter from imprecise touches near the center.

The steering input is calculated as:


input = Round(currentAngle / maximumAngle * 100) / 100

This gives two decimal places of precision. When the player releases the wheel, it smoothly returns to center at the configured reset speed.

The steering wheel uses Unity's EventTrigger system with three events: PointerDown (start tracking), Drag (update angle), and EndDrag (release and auto-center).

Joystick

A standard analog joystick handled by RCCP_UI_Joystick. It consists of a background sprite and a draggable handle sprite.

The joystick implements IDragHandler, IPointerUpHandler, and IPointerDownHandler from Unity's EventSystems.


Switching Controller Type at Runtime

You can change the active mobile controller type from code at any time:


// Switch to Gyro mode
RCCP.SetMobileController(RCCP_Settings.MobileController.Gyro);

// Switch to Joystick mode
RCCP.SetMobileController(RCCP_Settings.MobileController.Joystick);

// Switch to TouchScreen mode
RCCP.SetMobileController(RCCP_Settings.MobileController.TouchScreen);

// Switch to SteeringWheel mode
RCCP.SetMobileController(RCCP_Settings.MobileController.SteeringWheel);

There is also a ready-made UI component, RCCP_UI_SetMobileController, that you can attach to buttons in your own UI. It accepts an integer index:

IndexController
0TouchScreen
1Gyro
2SteeringWheel
3Joystick

How Mobile Input Flows

Understanding the input pipeline helps when debugging:

  1. RCCP_MobileInputs reads values from its assigned UI components (throttle, brake, left, right, ebrake, nos, steeringWheel, joystick) every frame in Update()
  2. It computes combined values: steerInput = -left.input + right.input + steeringWheel.input + joystick.inputHorizontal (only the active controller contributes since others are disabled)
  3. In Gyro mode, the accelerometer reading is added to steerInput
  4. NOS input is added to throttle input (then clamped to 0-1)
  5. All values are clamped to their valid ranges
  6. RCCP_InputManager reads these values from RCCP_MobileInputs.Instance and passes them to the active vehicle

UI Canvas Setup

The mobile UI is part of the RCCP UI Canvas prefab, which is referenced in RCCP_Settings. The canvas contains all mobile control elements, and RCCP_MobileInputs manages which elements are visible based on the active controller type.

Sporty Mobile UI Skin

The current default mobile UI is the Sporty skin. The legacy button set was replaced in V2.31.1+ to give a clearer, more focused on-screen control surface:

The four input methods (TouchScreen, Gyro, SteeringWheel, Joystick) are unchanged -- only the button artwork and the labels for handbrake / NOS were updated.

Customizing the Layout

This section covers changing the layout at author time, in the prefab. To let the player rearrange the controls at runtime, see Customizable Control Layout further down this chapter.

To customize button positions, sizes, or visuals:

  1. Locate the RCCP UI Canvas prefab in your scene (or in the project at the path referenced by RCCP Settings)
  2. Open the prefab and find the mobile control GameObjects
  3. Modify RectTransform positions, sizes, and Image sprites as needed
  4. The RCCP_UIController, RCCP_UI_SteeringWheelController, and RCCP_UI_Joystick components must remain on the correct GameObjects for input to work
  5. Make sure the RCCP_MobileInputs component references are not broken after rearranging

Required Scene Components


Customizable Control Layout

Added in V3.0.0.

Players can drag the on-screen controls into an arrangement that suits their hands, their device, and their grip. The feature is driven by RCCP_UI_MobileLayoutManager, which is already wired up in the V3.0.0 RCCP_Canvas prefab -- there is nothing to add if you use the shipped canvas.

What the Player Sees

  1. Open the settings panel and press Edit Controls.
  2. The driving controls become draggable. An overlay appears with a hint and two buttons.
  3. Drag any control anywhere on screen.
  4. Press Done to keep the arrangement, or Restore Defaults to put everything back where it shipped.

The arrangement is saved automatically and restored the next time the game runs.

Edit Controls and Reset Controls in the settings panel are only interactable while the mobile controller is enabled -- there is nothing to rearrange otherwise. They stay visible rather than disappearing, so the settings grid does not reflow when the controller-type dropdown next to them changes.

Why Dragging Does Not Drive the Car

While the editor is open the manager takes control away from the active vehicle and suspends every touch input component, so dragging the throttle pedal across the screen never applies throttle.

Two details make this safe in practice:

If the player switches vehicles mid-edit, the manager follows the switch and locks the new vehicle instead.

How Positions Survive Different Screens

Positions are stored normalized (0 to 1) inside the controls container rather than in pixels, and on every apply the control is re-anchored to the nearest of nine anchor zones -- the four corners, the four edge midpoints, and the center.

That combination is what makes a layout portable. A button the player drags to the bottom-left is stored as a bottom-left position and re-anchored to the bottom-left corner, so a layout authored on a 20:9 phone lands correctly on a 4:3 tablet instead of dangling off its original anchor. It also survives safe-area changes and device rotation: when the container resizes, the saved layout is simply re-applied against the new size.

During a drag the anchor is deliberately left alone and only committed on release, so a control does not jump between zones under the player's finger.

Which Controls Are Movable

Every direct child of the controls container carrying one of these components:

Controls that are currently switched off are captured too -- the joystick, the steering wheel, and the NOS button on a car without nitrous. That way, switching the controller type later reveals a correctly positioned control rather than one still sitting at its factory spot.

Settings

FieldTypeDefaultDescription
controlsContainerRectTransform(auto)Parent rect of the mobile controls. Falls back to the mobile canvas from RCCP_MobileInputs if left empty.
editorOverlayGameObject--Overlay shown while the editor is open (hint text, Restore and Done buttons).
hideWhileEditingGameObject[]--Objects hidden while editing so their buttons cannot be tapped by accident.
edgePaddingfloat12Minimum gap kept between a control and the container edge, in canvas units.

Scripting


RCCP_UI_MobileLayoutManager layout = FindFirstObjectByType();

layout.EnterEditMode();      // Open the editor
layout.ExitEditMode();       // Close and save
layout.CancelEditMode();     // Close and discard -- everything returns to where the session started
layout.ToggleEditMode();     // Open if closed, close and save if open

layout.RestoreDefaults();    // Factory layout, and forget the saved one. Safe to call any time.
layout.SaveLayout();         // Save the current arrangement
layout.LoadLayout();         // Re-apply the saved arrangement
layout.CaptureControls();    // Re-scan, for projects that spawn controls at runtime

bool editing = layout.IsEditing;
bool anyEditing = RCCP_UI_MobileLayoutManager.IsAnyEditing;   // static

IsAnyEditing is what the modern dashboard checks before opening its settings panel, so the panel cannot appear on top of the layout editor. Use it in your own UI for the same reason.

Saved Data and Versioning

Layouts are stored in PlayerPrefs under keys prefixed RCCP_MobileLayout_, two floats per control, plus a stored format version.

RCCP_UI_MobileLayoutManager.LayoutVersion is a constant compared against that stored version on load. If you change the shipped default layout, bump it. A layout saved under an older version is discarded rather than applied, so players get your new default instead of a half-broken mixture of the two. A control with no saved entry is left exactly as authored, which is why a project that never uses this feature behaves identically to before.

Nothing is written to disk unless the player actually moved something, so an interrupted or untouched editing session cannot overwrite a good saved layout.


Safe Area Support

Added in V3.0.0.

RCCP_UI_MobileSafeArea insets a full-stretch RectTransform to the device safe area, so notches, punch holes, rounded corners, and gesture bars never sit on top of the touch controls. It is already on the controls rect in the V3.0.0 RCCP_Canvas prefab.

It drives the rect's anchors from Screen.safeArea and re-applies the rect's authored offsets on top of the inset, so every child anchored to a corner follows automatically without being re-authored. It re-evaluates whenever the safe area, resolution, or orientation changes, and is a cheap no-op when nothing has.

FieldTypeDefaultDescription
applyHorizontalbooltrueApply the left/right insets. Disable to keep full screen width.
applyVerticalbooltrueApply the top/bottom insets. Disable to keep full screen height.
extraPaddingfloat0Additional inset on every edge, in screen pixels, on top of the reported safe area.

Three real-device behaviors are handled deliberately, and are worth knowing before you write your own version:

extraPadding is clamped so it can never invert the rect, however large a value you set.

To apply it to your own UI, add the component to a full-stretch RectTransform that parents the elements you want inset. Call Apply(true) to force an immediate recalculation after you change anything yourself.


Platform Notes


Common Issues

ProblemLikely CauseSolution
Controls not showing on devicemobileControllerEnabled is falseEnable it in RCCP Settings
Steering too sensitive in Gyro modegyroSensitivity too highLower the value (try 1.0 - 2.0)
Steering too sluggish in Gyro modegyroSensitivity too lowRaise the value (try 3.0 - 5.0)
Buttons not responding to touchMissing EventSystem in sceneAdd an EventSystem GameObject to the scene
NOS button not visibleVehicle has no NOS addonAdd RCCP NOS component to the vehicle via OtherAddonsManager
TouchScreen buttons respond slowlyLow sensitivity on RCCP_UIControllerIncrease the sensitivity value on the button component
Input sticks after switching controllersUI element not resettingInputs auto-reset on enable/disable; check that references in RCCP_MobileInputs are assigned
Steering wheel jitters near centerDead zone too smallIncrease steeringWheelCenterDeadZoneRadius
Edit Controls / Reset Controls buttons greyed outMobile controller is disabledEnable mobileControllerEnabled -- there is nothing to rearrange otherwise
Settings panel will not openThe control layout editor is openClose the layout editor first. This is intentional, so restart / photo mode cannot be reached mid-edit
Vehicle stays uncontrollable after editingNone -- control is only handed back if it was enabled to begin withCheck whether your own code had already set canControl to false
Layout editor does nothing / warns about no movable controlsControls are not direct children of the container, or lack an input componentMovable controls must be direct children carrying RCCP_UIController, RCCP_UI_Joystick, or RCCP_UI_SteeringWheelController
Saved layout looks wrong after updating the gameThe shipped default layout changed but LayoutVersion was not bumpedBump RCCP_UI_MobileLayoutManager.LayoutVersion so old saves are discarded
Controls sit under a notch or gesture barNo RCCP_UI_MobileSafeArea on the controls rectAdd it to the full-stretch rect that parents the controls
UI is inset too aggressively on one deviceReported safe area plus extraPaddingLower extraPadding, or disable applyHorizontal / applyVertical for that axis

Next Steps


Support: bonecrackergames@gmail.com | www.bonecrackergames.com

Need help? See Troubleshooting