Events System
RCC_Events is a centralized event hub that fires at every interesting moment in a vehicle's life — spawn, destroy, collision, gear shift, indicator toggle, camera change, and so on. Subscribing to these events is the recommended way to integrate your game code with RCC because it doesn't require modifying any RCC scripts.
This document covers every event, what triggers it, and shows working subscription patterns.
How RCC_Events Works
RCC_Events is a plain static class. Each event is a static C# delegate. You subscribe in OnEnable and unsubscribe in OnDisable:
void OnEnable() { RCC_Events.OnRCCPlayerSpawned += MyHandler; }
void OnDisable() { RCC_Events.OnRCCPlayerSpawned -= MyHandler; }
void MyHandler(RCC_CarControllerV4 vehicle) {
Debug.Log("New player vehicle: " + vehicle.name);
}
This is the standard C# event pattern. Always unsubscribe in OnDisable to avoid memory leaks and null-reference exceptions when the subscribing GameObject is destroyed.
Event Categories
The events are grouped into:
- Vehicle Lifecycle — spawn, destroy, collide.
- AI Lifecycle — AI spawn, AI destroy.
- Camera — camera spawn.
- Scene Management — behavior change, vehicle change.
- Input Events — engine toggle, gear shift, indicator toggle, etc.
Vehicle Lifecycle Events
OnRCCPlayerSpawned
public delegate void onRCCPlayerSpawned(RCC_CarControllerV4 RCC);
public static event onRCCPlayerSpawned OnRCCPlayerSpawned;
Fires after a vehicle is registered as the player. Triggered by RCC.RegisterPlayerVehicle() or by the SceneManager auto-registering a vehicle tagged "Player."
Use cases: bind your HUD to the new vehicle, attach a follow camera, update minimap.
Example: Bind HUD to the spawned player
using UnityEngine;
public class HUDBinder : MonoBehaviour {
public Text speedometer;
private RCC_CarControllerV4 currentVehicle;
void OnEnable() { RCC_Events.OnRCCPlayerSpawned += BindToVehicle; }
void OnDisable() { RCC_Events.OnRCCPlayerSpawned -= BindToVehicle; }
void BindToVehicle(RCC_CarControllerV4 vehicle) {
currentVehicle = vehicle;
}
void Update() {
if (currentVehicle != null) {
speedometer.text = $"{currentVehicle.speed:F0} km/h";
}
}
}
OnRCCPlayerDestroyed
public delegate void onRCCPlayerDestroyed(RCC_CarControllerV4 RCC);
public static event onRCCPlayerDestroyed OnRCCPlayerDestroyed;
Fires when the active player vehicle is de-registered — either because of RCC.DeRegisterPlayerVehicle() or because the vehicle's OnDestroy was called.
Use cases: clean up HUD bindings, detach the camera, save player state.
OnRCCPlayerCollision
public delegate void onRCCPlayerCollision(RCC_CarControllerV4 RCC, Collision collision);
public static event onRCCPlayerCollision OnRCCPlayerCollision;
Fires inside the player vehicle's OnCollisionEnter. The collision parameter is Unity's standard Collision — you have access to contact points, relative velocity, the other collider, etc.
Use cases: trigger crash audio, subtract health, play damage VFX, track collision count.
Example: Track crashes for a "no-crash" achievement
public class CrashTracker : MonoBehaviour {
public int crashCount = 0;
public float crashThresholdSpeed = 5f; // m/s
void OnEnable() { RCC_Events.OnRCCPlayerCollision += OnCollision; }
void OnDisable() { RCC_Events.OnRCCPlayerCollision -= OnCollision; }
void OnCollision(RCC_CarControllerV4 vehicle, Collision collision) {
if (collision.relativeVelocity.magnitude > crashThresholdSpeed) {
crashCount++;
// achievement failed, etc.
}
}
}
AI Lifecycle Events
OnRCCAISpawned
public delegate void onRCCAISpawned(RCC_AICarController RCCAI);
public static event onRCCAISpawned OnRCCAISpawned;
Fires when an AI vehicle becomes active.
Use cases: add to a minimap, populate a hostile list, count active enemies.
OnRCCAIDestroyed
public delegate void onRCCAIDestroyed(RCC_AICarController RCCAI);
public static event onRCCAIDestroyed OnRCCAIDestroyed;
Fires when an AI vehicle is removed.
Use cases: remove from minimap, decrement enemy count, mission completion.
Camera Event
OnBCGCameraSpawned
public delegate void onBCGCameraSpawned(GameObject BCGCamera);
public static event onBCGCameraSpawned OnBCGCameraSpawned;
Fires after the RCC camera is instantiated.
Use cases: attach post-processing, configure FOV, apply custom follow logic.
Scene Management Events
OnBehaviorChanged
public delegate void onBehaviorChanged();
public static event onBehaviorChanged OnBehaviorChanged;
Fires when RCC.SetBehavior() or RCC_SceneManager.Instance.SetBehavior() changes the global driving behavior preset.
Use cases: update UI label to show new mode, play sound, apply secondary tuning.
Example: Show behavior change toast
public class BehaviorToast : MonoBehaviour {
public Text toastText;
public float toastDuration = 2f;
void OnEnable() { RCC_Events.OnBehaviorChanged += ShowToast; }
void OnDisable() { RCC_Events.OnBehaviorChanged -= ShowToast; }
void ShowToast() {
string name = RCC_Settings.Instance.selectedBehaviorType?.behaviorName ?? "Default";
toastText.text = $"Behavior: {name}";
CancelInvoke(nameof(HideToast));
toastText.enabled = true;
Invoke(nameof(HideToast), toastDuration);
}
void HideToast() {
toastText.enabled = false;
}
}
OnVehicleChanged
public delegate void onVehicleChanged();
public static event onVehicleChanged OnVehicleChanged;
Fires when the active player vehicle is swapped (e.g., car selection menu, vehicle change at runtime).
Use cases: refresh HUD bindings, telemetry, AI targets.
Input Events
These fire once each time the corresponding input action is triggered. They're great for one-shot reactions.
OnStartStopEngine
Fires when the engine ignition input is pressed.
Use cases: ignition audio, dashboard "ignition" indicator, custom engine state.
OnLowBeamHeadlights / OnHighBeamHeadlights
Fires when low or high beam input is toggled.
Use cases: HUD indicator update, AI visibility logic.
OnChangeCamera
Fires when the change-camera input is pressed.
Use cases: cycle custom camera modes, update HUD overlay per view, play camera transition sound.
OnIndicatorLeft / OnIndicatorRight / OnIndicatorHazard
Fires when each indicator input is toggled.
Use cases: HUD blinkers, indicator click sound, driving-school style validation.
Example: Play tick-tock sound on indicator toggle
public class IndicatorTickSound : MonoBehaviour {
public AudioSource tickAudio;
void OnEnable() {
RCC_Events.OnIndicatorLeft += PlayTick;
RCC_Events.OnIndicatorRight += PlayTick;
RCC_Events.OnIndicatorHazard += PlayTick;
}
void OnDisable() {
RCC_Events.OnIndicatorLeft -= PlayTick;
RCC_Events.OnIndicatorRight -= PlayTick;
RCC_Events.OnIndicatorHazard -= PlayTick;
}
void PlayTick() {
tickAudio.Play();
}
}
OnInteriorlights
Fires when the interior light input is toggled.
OnGearShiftUp / OnGearShiftDown
Fires when the gearbox shifts up or down.
Use cases: shift audio (custom variations), force feedback, telemetry logging.
OnNGear
public delegate void onNGear(bool state);
Fires when the neutral gear input toggles. state is true when neutral is engaged, false when released.
OnSlowMotion
public delegate void onSlowMotion(bool state);
Fires when slow motion is toggled. state is true when active.
Use cases: scale audio pitch alongside Time.timeScale, trigger cinematic VFX.
OnRecord / OnReplay
Fires when record / replay input is pressed.
Use cases: HUD overlays for record/replay status, disable user controls during playback.
OnLookBack
public delegate void onLookBack(bool state);
Fires when the look-back input changes state. state is true while held.
OnTrailerDetach
Fires when the trailer-detach input is pressed.
Use cases: HUD update, custom trailer-release logic (cargo drops, mission triggers).
Defensive Subscribe Pattern
If your game has multiple scenes and the subscribing GameObject might be created before or after the event firer, use a defensive pattern:
void OnEnable() {
RCC_Events.OnRCCPlayerSpawned += HandleSpawn;
// also handle the case where the player is already spawned:
var current = RCC_SceneManager.Instance.activePlayerVehicle;
if (current != null) HandleSpawn(current);
}
This way, your handler runs both for vehicles that spawn after you subscribe and for the existing player vehicle if there is one.
Firing Events Yourself
Each event has a corresponding Event_OnXxx static method that fires it:
RCC_Events.Event_OnRCCPlayerSpawned(myVehicle);
You normally don't call these — they're called internally by RCC's controller and SceneManager. But if you're writing a custom integration (e.g., a different way to register player vehicles), you can call them to keep the event system consistent.
Conditional Events (BCG_ENTEREXIT)
Some events only exist when the BCG_ENTEREXIT define is set. These are for the legacy BCG Shared Assets Enter/Exit system, which has been removed in V5. If you see references to OnPlayerEnteredVehicle or OnPlayerExitedVehicle, those are vestiges of the removed system — they won't fire in a stock V5 install.
Common Event Pitfalls
"Subscribed but my handler isn't called"
Most common: you subscribed in Start() instead of OnEnable(). If the event fires during scene load (before Start), you miss it. Use OnEnable and / or query the current state on subscription.
"My handler is called multiple times"
You subscribed multiple times without unsubscribing. Always pair += with a -= in OnDisable.
"NullReferenceException in my handler after scene unload"
You forgot to unsubscribe in OnDisable. After scene change, the static event still holds a reference to your destroyed GameObject's handler — and calling it throws.
"Event fires but the vehicle parameter is null"
If a vehicle is being destroyed at the moment the event fires, it might already be null by the time your handler runs. Always null-check.
Next Steps
- 23 — Scripting API — the static
RCCclass. - 17 — Overriding Inputs — for input flow.
- 16 — Input System — how input events are triggered.