Mobile Controls
Table of Contents
- Mobile Controls
- Overview
- Enabling Mobile Controls
- Settings Reference
- Controller Types
- TouchScreen
- Gyro (Accelerometer)
- Steering Wheel
- Joystick
- Switching Controller Type at Runtime
- How Mobile Input Flows
- UI Canvas Setup
- Sporty Mobile UI Skin
- Customizing the Layout
- Required Scene Components
- Customizable Control Layout
- What the Player Sees
- Why Dragging Does Not Drive the Car
- How Positions Survive Different Screens
- Which Controls Are Movable
- Settings
- Scripting
- Saved Data and Versioning
- Safe Area Support
- Platform Notes
- Common Issues
- Next Steps
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:
| Controller | Steering Method | UI Elements Shown |
|---|---|---|
| TouchScreen | Left/Right buttons | Steer Left, Steer Right, Throttle, Brake, Handbrake, NOS |
| Gyro | Device tilt (accelerometer) | Throttle, Brake, Handbrake, NOS (no steering buttons) |
| SteeringWheel | Rotatable on-screen wheel | Steering Wheel, Throttle, Brake, Handbrake, NOS |
| Joystick | Draggable analog stick | Joystick, Throttle, Brake, Handbrake, NOS |
The NOS button only appears when the active player vehicle has a NOS addon component attached.
Enabling Mobile Controls
- Open RCCP Settings: Tools > BoneCracker Games > Realistic Car Controller Pro > Settings
- In the Mobile Input section, enable
mobileControllerEnabled(set totrue) - Select the desired controller type from the
mobileControllerdropdown
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
| Field | Type | Default | Description |
|---|---|---|---|
mobileControllerEnabled | bool | false | Master toggle for mobile controls |
mobileController | enum | TouchScreen | Active controller type |
gyroSensitivity | float | 2.5 | Accelerometer sensitivity multiplier (Gyro mode only) |
Controller Types
TouchScreen
The simplest mobile input mode. Six on-screen buttons handle all vehicle controls:
- Steer Left / Steer Right -- each is a
RCCP_UIControllerthat outputs a value from 0 to 1 - Throttle -- ramps up while held, ramps down when released
- Brake -- same behavior as throttle
- Handbrake -- toggle-style press
- NOS -- only visible when the vehicle has a NOS addon
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:
| Parameter | Default | What It Does |
|---|---|---|
sensitivity | 5.0 | How fast the input value ramps up toward 1 when the button is held. Higher values produce snappier response. |
gravity | 5.0 | How 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.
- The X component of the acceleration vector is multiplied by
gyroSensitivityand added to the steering input - The steering left/right buttons are hidden
- Throttle, brake, handbrake, and NOS buttons remain visible and functional
- The accelerometer device is automatically enabled when Gyro mode is active
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.
| Parameter | Default | Description |
|---|---|---|
steeringWheelMaximumsteerAngle | 270 | Maximum rotation angle in degrees (both directions). The wheel can rotate from -270 to +270. |
steeringWheelResetPosSpeed | 20 | How fast the wheel auto-centers when released. Uses Mathf.MoveTowards scaled by Time.deltaTime * 100. |
steeringWheelCenterDeadZoneRadius | 5 | Pixel 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.
inputHorizontal(range -1 to 1) is used for steeringinputVertical(range -1 to 1) is available but not used for throttle/brake by default- The handle snaps back to center when released
- If the drag distance exceeds half the background size, the input is clamped to a normalized direction (magnitude of 1)
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:
| Index | Controller |
|---|---|
| 0 | TouchScreen |
| 1 | Gyro |
| 2 | SteeringWheel |
| 3 | Joystick |
How Mobile Input Flows
Understanding the input pipeline helps when debugging:
RCCP_MobileInputsreads values from its assigned UI components (throttle,brake,left,right,ebrake,nos,steeringWheel,joystick) every frame inUpdate()- It computes combined values:
steerInput = -left.input + right.input + steeringWheel.input + joystick.inputHorizontal(only the active controller contributes since others are disabled) - In Gyro mode, the accelerometer reading is added to
steerInput - NOS input is added to throttle input (then clamped to 0-1)
- All values are clamped to their valid ranges
RCCP_InputManagerreads these values fromRCCP_MobileInputs.Instanceand 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:
- Removed legacy buttons: Demo, EBrake, NOS, Fuel, NOS-Bottle.
- Added clearer buttons: HandBrake, NOS1.
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:
- Locate the RCCP UI Canvas prefab in your scene (or in the project at the path referenced by RCCP Settings)
- Open the prefab and find the mobile control GameObjects
- Modify RectTransform positions, sizes, and Image sprites as needed
- The
RCCP_UIController,RCCP_UI_SteeringWheelController, andRCCP_UI_Joystickcomponents must remain on the correct GameObjects for input to work - Make sure the
RCCP_MobileInputscomponent references are not broken after rearranging
Required Scene Components
- An EventSystem must be present in the scene for touch/pointer input to work
- The RCCP UI Canvas must be in the scene (it is normally instantiated automatically if referenced in Settings)
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
- Open the settings panel and press Edit Controls.
- The driving controls become draggable. An overlay appears with a hint and two buttons.
- Drag any control anywhere on screen.
- 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:
- The previous
canControlstate is remembered, and control is handed back only if the vehicle was controllable to begin with. A car your game had deliberately locked stays locked. - If the canvas is disabled while the editor is open, the editor closes itself first. The vehicle can never be left stuck out of control.
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:
RCCP_UIController-- throttle, brake, handbrake, NOS, steer left, steer rightRCCP_UI_JoystickRCCP_UI_SteeringWheelController
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
| Field | Type | Default | Description |
|---|---|---|---|
controlsContainer | RectTransform | (auto) | Parent rect of the mobile controls. Falls back to the mobile canvas from RCCP_MobileInputs if left empty. |
editorOverlay | GameObject | -- | Overlay shown while the editor is open (hint text, Restore and Done buttons). |
hideWhileEditing | GameObject[] | -- | Objects hidden while editing so their buttons cannot be tapped by accident. |
edgePadding | float | 12 | Minimum 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.
| Field | Type | Default | Description |
|---|---|---|---|
applyHorizontal | bool | true | Apply the left/right insets. Disable to keep full screen width. |
applyVertical | bool | true | Apply the top/bottom insets. Disable to keep full screen height. |
extraPadding | float | 0 | Additional 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:
- Platforms that report an empty safe area fall back to the full screen rather than collapsing the UI to nothing.
- Skinned Android builds that report a safe area larger than the screen, or an inverted one, are clamped where possible and rejected only when genuinely unusable -- and a rejected value is not cached, so the next frame retries instead of one bad report suppressing every update until the next rotation.
- A zero-sized screen, which can occur for a frame while the window is resizing or the app is backgrounded, is skipped.
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
- iOS and Android are both fully supported
- Gyro mode uses
UnityEngine.InputSystem.Accelerometer, which works on most modern mobile devices - The accelerometer device is enabled automatically by RCCP when Gyro mode is selected
- Test mobile controls using Unity Remote (for quick iteration) or by building directly to device (for accurate touch behavior)
- On desktop platforms, mobile controls still work if
mobileControllerEnabledis set totrue-- this is useful for testing
Common Issues
| Problem | Likely Cause | Solution |
|---|---|---|
| Controls not showing on device | mobileControllerEnabled is false | Enable it in RCCP Settings |
| Steering too sensitive in Gyro mode | gyroSensitivity too high | Lower the value (try 1.0 - 2.0) |
| Steering too sluggish in Gyro mode | gyroSensitivity too low | Raise the value (try 3.0 - 5.0) |
| Buttons not responding to touch | Missing EventSystem in scene | Add an EventSystem GameObject to the scene |
| NOS button not visible | Vehicle has no NOS addon | Add RCCP NOS component to the vehicle via OtherAddonsManager |
| TouchScreen buttons respond slowly | Low sensitivity on RCCP_UIController | Increase the sensitivity value on the button component |
| Input sticks after switching controllers | UI element not resetting | Inputs auto-reset on enable/disable; check that references in RCCP_MobileInputs are assigned |
| Steering wheel jitters near center | Dead zone too small | Increase steeringWheelCenterDeadZoneRadius |
| Edit Controls / Reset Controls buttons greyed out | Mobile controller is disabled | Enable mobileControllerEnabled -- there is nothing to rearrange otherwise |
| Settings panel will not open | The control layout editor is open | Close the layout editor first. This is intentional, so restart / photo mode cannot be reached mid-edit |
| Vehicle stays uncontrollable after editing | None -- control is only handed back if it was enabled to begin with | Check whether your own code had already set canControl to false |
| Layout editor does nothing / warns about no movable controls | Controls are not direct children of the container, or lack an input component | Movable controls must be direct children carrying RCCP_UIController, RCCP_UI_Joystick, or RCCP_UI_SteeringWheelController |
| Saved layout looks wrong after updating the game | The shipped default layout changed but LayoutVersion was not bumped | Bump RCCP_UI_MobileLayoutManager.LayoutVersion so old saves are discarded |
| Controls sit under a notch or gesture bar | No RCCP_UI_MobileSafeArea on the controls rect | Add it to the full-stretch rect that parents the controls |
| UI is inset too aggressively on one device | Reported safe area plus extraPadding | Lower extraPadding, or disable applyHorizontal / applyVertical for that axis |
Next Steps
- Modern UI and Theming -- the redesigned canvas, the dashboard, gauge styles, and runtime theming
- Inputs -- Keyboard and gamepad input configuration
- Logitech Steering Wheels -- Hardware racing wheel support
- Settings -- Full RCCP Settings reference including mobile options
Support: bonecrackergames@gmail.com | www.bonecrackergames.com
Need help? See Troubleshooting