Modern UI and Theming

Table of Contents

V3.0.0 ships a completely redesigned runtime UI. The RCCP_Canvas prefab was rebuilt around a new dashboard, a new sprite set, four selectable gauge styles, and a sprite-swap theming system that lets the player re-skin the HUD at runtime.

This chapter covers the redesigned canvas, the RCCP_UI_ModernDashboard component that drives it, and the theme system. For the on-screen touch controls -- including the new drag-to-arrange layout editor -- see Mobile Controls.


What Changed in V3.0.0

Before V3.0.0V3.0.0
Canvas prefabRCCP_Canvas.prefabRCCP_Canvas.prefab, rebuilt
Dashboard driverRCCP_UIManagerRCCP_UI_ModernDashboard (inherits RCCP_UIManager)
GaugeOne fixed clusterFour selectable styles
SkinningEdit the prefab by handRCCP_UI_Theme assets, swappable at runtime
Sprite packingSprite Atlas V1Sprite Atlas V2 (required)

The old canvas is still in the package as RCCP_Canvas_Old.prefab, in the same folder. Nothing references it -- it is there purely so a project that customized the previous canvas has something to fall back to or diff against.

If You Customized the Old Canvas

Read this before updating. The redesign replaces the prefab wholesale, so canvas edits you made in an earlier version are not carried over. You have two options:

  1. Take the redesign. Re-apply your changes on top of the new RCCP_Canvas.prefab. This is the recommended path -- the new canvas is what future versions build on.
  2. Keep what you had. Point RCCP_Settings at your own copy of the previous canvas, or at the shipped RCCP_Canvas_Old.prefab. Everything continues to work; you simply do not get the new dashboard, gauge styles, theming, or the mobile layout editor, all of which live in the new prefab.

This is the change that moved RCCP to a major version number. Nothing else in V3.0.0 requires you to redo work.

Sprite Atlas V2 Is Required

The new UI sprites are packed by Textures/UI/ModernUI/RCCP_UIM.spriteatlasv2, which only packs when the project's sprite packer mode is set to Sprite Atlas V2:

Edit > Project Settings > Editor > Sprite Packer > Mode: Sprite Atlas V2

RCCP ships with this already set. But it is a project-wide setting, so a project that imported RCCP into an existing codebase keeps whatever mode it already had. If the mode is left on the older V1 setting, the atlas never packs and the UI sprites do not resolve -- the canvas renders with missing or blank graphics. Nothing in the console warns about it, so check this setting first if the new UI looks broken.


The Modern Dashboard

RCCP_UI_ModernDashboard (Scripts/UI/) is the HUD driver. It is embedded in RCCP_Canvas.prefab -- you do not add it to a scene yourself, and there is no separate dashboard prefab to instantiate.

It inherits RCCP_UIManager, which is deliberate: existing code that calls RCCP_UIManager.Instance, listens to the RCCP UI spawn events, or reads RCCP_SceneManager.activePlayerCanvas keeps working unchanged against the new canvas.

It drives:

Gauge Styles

The RPM cluster ships in four styles. The player picks one from the settings panel; the choice is saved to PlayerPrefs under the key RCCP_ModernGaugeStyle and restored on the next run.

IndexStyleDescription
0RadialThe default. A circular RPM arc with a needle tick.
1AnalogA classic sweeping needle on a dial.
2DigitalA horizontal RPM bar with a numeric readout.
3MinimalA stripped-back cluster for a clean screen.

Each style has its own root GameObject, listed in the gaugeStyleRoots array in the same order as the table. Switching styles activates one root and deactivates the others -- nothing is instantiated or destroyed.

From your own code:


RCCP_UI_ModernDashboard dashboard = FindFirstObjectByType();

// Index matches the table above.
dashboard.SetGaugeStyle(2);      // Digital -- also saves the choice

// Re-apply the current selection without saving (e.g. after building UI at runtime).
dashboard.ApplyGaugeStyle();

SetGaugeStyle clamps its argument to the valid range, so an out-of-range index is safe.

To add a fifth style you would add a root GameObject to gaugeStyleRoots and extend the GaugeStyle enum. Append new entries to the end of the enum -- the value is stored as an integer in PlayerPrefs and referenced by index in the array, so inserting in the middle silently reassigns every player's saved choice.

Settings Panel

The settings panel is opened by the on-screen button or the Options input, both of which route through ToggleSettings(). Two behaviors are worth knowing:


Theming

Theming swaps sprites. That is the whole model, and it is what makes it safe: layout, components, hierarchy, and behavior are never touched, so a theme cannot break the UI, and a broken theme is one wrong-looking sprite rather than a dead canvas.

The Pieces

RCCP_UI_Theme is a ScriptableObject holding a display name and a list of sprite replacements:

FieldTypeDescription
themeNamestringDisplay name of the theme.
spritePairsarrayEach entry maps an original sprite to the themed sprite that replaces it.

RCCP_UI_ThemeApplier is the MonoBehaviour that applies them. It sits on the canvas root:

FieldTypeDescription
themesarrayAvailable themes. Index 0 in the selector is the untouched default look; the array's themes start at selector index 1.
activeThemeintCurrent selection. 0 is default, 1..n map into themes.
themeDropdownTMP_DropdownOptional settings dropdown kept in sync with the selection.

RCCP ships one theme: Carbon, at Textures/UI/ModernUI/Themes/Carbon/RCCP_UI_Theme_Carbon.asset.

How It Applies

On enable, the applier reads the saved selection from PlayerPrefs (key RCCP_ModernUITheme) and applies it. On every apply it:

  1. Reverts every image it has previously touched back to the sprite it started with.
  2. Builds a lookup from the active theme's pairs.
  3. Walks every Image under the canvas -- including inactive ones -- and swaps any sprite present in the lookup, remembering the original first.

Because step 1 always runs, switching between themes and back to default is lossless; the applier never compounds one theme on top of another.


RCCP_UI_ThemeApplier applier = FindFirstObjectByType();

applier.SetTheme(0);    // Default look
applier.SetTheme(1);    // First theme in the themes array -- saves the choice

Making Your Own Theme

  1. Create the asset: Assets > Create > BoneCracker Games > Realistic Car Controller Pro > UI > UI Theme
  2. Give it a themeName.
  3. Author your replacement sprites. The simplest starting point is to duplicate the sprites under Textures/UI/ModernUI/ and restyle them -- keep the same dimensions and border settings so 9-slicing still behaves.
  4. Fill in spritePairs: original is the sprite the shipped canvas uses, themed is yours. You only need pairs for the sprites you actually want to change; anything unlisted keeps its default look.
  5. Add the asset to the themes array on the RCCP_UI_ThemeApplier on your canvas.
  6. If you use the settings dropdown, add a matching option to it. Remember the dropdown's index 0 is the default look, so your first theme is dropdown index 1.

Duplicate original sprites are ignored. If two pairs list the same original, only the first is used -- the lookup is built once and skips keys it already holds.


Common Issues

ProblemLikely CauseSolution
UI sprites missing, blank, or whiteSprite packer mode is not Sprite Atlas V2Edit > Project Settings > Editor > Sprite Packer > Mode: Sprite Atlas V2
My old canvas customizations are goneThe V3.0.0 canvas is a rebuilt prefab, not a patchRe-apply them to the new prefab, or point Settings at RCCP_Canvas_Old.prefab
Theme dropdown selects the wrong themeForgetting that dropdown index 0 is the default lookYour first theme is index 1, not 0
A theme changes nothingThe original sprite in a pair is not the sprite the canvas actually usesSelect the Image in the canvas, check which sprite it references, and use exactly that as original
Gauge style resets for existing players after an updateAn entry was inserted into the GaugeStyle enum instead of appendedAppend new styles to the end of the enum and the gaugeStyleRoots array
Settings panel will not openThe mobile control layout editor is openClose the layout editor first -- this is intentional
Custom scripts can no longer find the UI managerNone -- this still worksRCCP_UI_ModernDashboard inherits RCCP_UIManager, so RCCP_UIManager.Instance resolves to it

Next Steps


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

Need help? See Troubleshooting