Traffic Overtaker Overview

Traffic Overtaker by BoneCracker Games is a complete, ready-to-ship Unity project: an endless, arcade, one-button hold-to-overtake racing game. The player drives a single car down a two-lane highway where the right lane is their travel direction and the left lane carries oncoming traffic. An on-car AI driver (TO_OvertakeAI) computes every vehicle input — steering along the curving road, throttle, and brake — so the player's only decision is when to commit to a pass. Press and hold the Overtake button to pull into the oncoming lane and accelerate past the slow car ahead; release it to ease back to the right lane. It is easy to play and hard to master: there is exactly one source of danger (a head-on with oncoming traffic) and exactly one source of progress (successful overtakes), and the whole experience is built to chase a single endless high score, bestScoreOvertake.

This page explains what the asset is, how the core loop works, the risk model, and how scoring is computed — all grounded in the shipping code. If you are reskinning Traffic Overtaker into your own game, start here, then move on to 03_ProjectStructure.md and 04_SystemArchitecture.md to see how the pieces fit together.

What Traffic Overtaker Is

Traffic Overtaker is a complete project, not a code-only library: it ships with playable scenes, 14 player-vehicle prefabs, a main-menu showroom with a purchase and customization storefront, a curved-road treadmill, pooled traffic, audio, and a full HUD. The bundled vehicle physics layer is Realistic Car Controller Pro (RCCP) — clients do not import RCCP separately, and every player and traffic vehicle is a real RCCP-driven rigidbody. Because the AI authors the same RCCP_Inputs struct a human driver would, the vehicle roster, upgrades, customization, and genuine physics collisions all still matter; the car feels like a real RCCP vehicle even though no one is steering it manually.

The asset's own code lives entirely under Assets/TO/, uses the TO_ prefix, and sits in the BoneCrackerGames namespace (RCCP code stays global and keeps its RCCP_ prefix). The build targets Unity 6 (verified on 6000.3.6f1) with the Universal Render Pipeline (URP) in Linear color space, and the scripting define symbol BCG_TO gates the project's editor and runtime code. The four shipping scenes — TO_Scene_MainMenu, TO_Scene_Sunny, TO_Scene_Rainy, and TO_Scene_Night — are enabled in Build Settings and demonstrate the same gameplay under different lighting and weather skins.

Key Features

The asset bundles a proven highway/traffic/physics/storefront stack with a single distinctive control mechanic on top. The features below are what you get out of the box.

Feature What it provides
One-button AI driver TO_OvertakeAI writes RCCP_Inputs every FixedUpdate — steering, throttle, brake — so the player only decides when to overtake.
Two-lane oncoming road Right lane = your direction, left lane = oncoming danger, managed by TO_LaneManager.
RCCP physics Every vehicle is a real Realistic Car Controller Pro car; upgrades and customization affect handling.
14 player vehicles A roster spanning hatchbacks, coupes, muscle cars, SUVs, and a hot hatch, with one unlocked free and the rest priced.
Endless arcade scoring Overtakes, near-misses, high-speed time, and distance feed score and currency, persisted as bestScoreOvertake.
Storefront & customization Buy and unlock cars and apply RCCP customization (paint, wheels, spoilers, NOS, siren) in the main-menu showroom.
Four skinned scenes Sunny, Rainy, and Night gameplay scenes plus a main menu, all reskins of one template.
Editor tooling Custom inspectors, a scene-manager setup tool, a welcome window, and vehicle-setup validation under Tools > BoneCracker Games > Traffic Overtaker.

How It Works

The two-lane road

The road is exactly two lanes. The right lane is your direction of travel; the left lane carries oncoming traffic and is the only real danger in the game. TO_Player continuously finds the closest lane via FindClosestLane() and sets its oppositeDirection flag when the car is in the oncoming (left) lane — that single flag drives both the scoring weights and the head-on game-over logic. Slow same-direction cars sit in the right lane; oncoming cars are forced into the left lane. To pass, you must cross into the path of oncoming traffic and time your return.

The Overtake state machine

TO_OvertakeAI runs a four-state machine driven by the single Overtake button. The states below describe what the AI does on your behalf; the button only chooses between holding the lane and committing to a pass.

State Trigger AI behavior
Cruise Free road Accelerate toward a cruise-speed cap in the right lane, steering along the curving centerline. Safe, but earns almost nothing.
Following A slower car is caught ahead in your lane Adaptive-cruise (ACC) slows and sits behind the lead car without rear-ending it. You are now stuck.
Overtaking Overtake button HELD Ramp the commanded lateral offset from the right lane to the left (oncoming) lane as a smooth S-curve and accelerate to pass. The AI does not brake for oncoming.
Returning Overtake button RELEASED Ease back to the right lane. The only auto-safety is execution sanity: if the passed car is still alongside, hold at the lane edge until its rear bumper clears (anti-side-swipe), then tuck in.

The steering is a pure-pursuit controller on a lane-frame: the car is projected onto the centerline, a signed cross-track error and heading error are computed, and a smoothly ramped lateral offset turns each lane change into an S-curve rather than a step. The throttle and brake are an Adaptive Cruise Control gap controller that maps a gap-plus-closing-rate command to either throttle or brake (never both at once). On free road or while overtaking it regulates speed toward the cruise cap; while following it regulates the gap to the lead car. Crucially, oncoming cars are never used as a brake target. The full control math, gains, and tuning live in the planning document Planning/control-system.md; see 04_SystemArchitecture.md for how the AI plugs into RCCP.

Race flow

TO_GamePlayManager orchestrates a run. On Start() it reads the selected car index from PlayerPrefs, fixes the mode to Mode.Overtake, and calls SpawnPlayer(), which instantiates the chosen vehicle through RCCP.SpawnRCC(), hands full input authority to the AI (externalControl = true, overridePlayerInputs = true, overrideExternalInputs = true), and attaches TO_OvertakeAI. A countdown coroutine (StartRaceDelayed) waits four seconds, flips gameStarted true, and fires Event_OnRaceStarted. The run ends when the player crashes: TO_Player.GameOver() calls CrashedPlayer() on the manager, which fires Event_OnPlayerDied and routes through FinishRace() to persist the high score under the bestScoreOvertake key.

There is exactly one game mode. The Mode enum in TO_GamePlayManager is declared as enum Mode { Overtake } and mode is forced to Mode.Overtake in Start() — the Highway-Racer-2 modes (TwoWay, TimeAttack, Bomb) that this project was derived from have been stripped. If you are reskinning, you do not need to wire mode selection; the cross-scene SelectedModeIndex key exists only for compatibility.

The Risk Model — "The Player Owns the Risk"

The defining design rule is that the AI guarantees smooth execution, never your safety. While overtaking, the AI commits to the left lane and will not auto-retreat for oncoming traffic. If an oncoming car arrives and you did not release the Overtake button in time, you crash. This is intentional: every pass is a real decision with real stakes, which is what makes a one-button game hard to master.

This rule is enforced concretely in TO_Player.OnCollisionEnter(). A collision is only considered when the impact impulse exceeds minimumCollisionForGameOver (4). If the car that was hit is an oncoming car (oppositeDirection == true) and the impact is frontal — the in-plane contact normal aligned with the car's travel axis at or above headOnFrontalDot (0.5) — the result is instant death: damage is set to 100, the explosion VFX (Settings.explosionEffect) spawns at the contact point, and GameOver() is called immediately. A glancing side-swipe of an oncoming car (frontal value below the cone) falls through to ordinary damage accrual, the same as a same-direction knock.

Accumulated side-swipe damage is the second way to end a run. Each surviving collision adds impulse * 3f to damage, and the run ends when damage reaches 100. The only automatic safety anywhere in the game is the execution-sanity hold during the Returning state — holding at the lane edge until a just-passed car clears so you do not side-swipe the car you overtook. That is collision-avoidance for the pass you already made, explicitly not protection from oncoming traffic.

How Scoring Works

Score and currency are accumulated entirely in TO_Player, using values configured in TO_Settings. There are four contributors: overtakes, near-misses, a continuous high-speed/distance trickle, and an end-of-run money payout. The concrete methods named below are the real ones in TO_Player.cs.

Overtakes — the core score driver

CheckOvertakes() (run every FixedUpdate) edge-detects when a same-direction traffic car that was clearly ahead has fallen clearly behind, and calls RegisterOvertake() once per pass. Each overtake awards overtakePoints (250) multiplied by a chain factor: chain = Mathf.Clamp(combo, 1, overtakeChainCap) where overtakeChainCap is 10. So a single pass is worth 250 points, and a sustained chain caps the multiplier at 10× (2,500 points per pass). Oncoming cars are never counted as overtakes — they are the danger, not progress.

Near-misses — the high-value bonus

CheckNearMiss() raycasts 2 m to both sides of the car against the traffic layer; when a car clears, RegisterNearMiss() fires. The points are (int)(100f * Mathf.Clamp(combo / 1.5f, 1f, 20f) * weight), where weight is oncomingNearMissMultiplier (4) when the cleared car was oncoming, and 1 otherwise. In other words, squeezing back into the right lane just ahead of oncoming traffic is the most lucrative move in the game — a 4× weighting on top of the combo chain. Both overtakes and near-misses increment the shared combo / maxCombo counters, which reset after roughly two seconds without a new event.

High-speed and distance trickle

While the run is active, TO_Player.Update() adds a small continuous score (CarController.speed * Settings.passiveScoreRate * Time.deltaTime, where passiveScoreRate is a deliberately tiny 0.01) whenever speed is at or above minimumSpeedForGainScore (80 km/h). Separately, it accrues highSpeedTotal time whenever speed is at or above minimumSpeedForHighSpeed (140 km/h) — this feeds the HUD's high-speed indicator only; it is no longer converted to currency. It also tracks total distance in kilometers, which does feed the end-of-run payout.

End-of-run currency payout

When GameOver() runs, three currency awards are computed and added via TO_API.AddCurrency(). This is a risk-weighted payout: overtakes are the dominant coin source, real near-misses second, and distance a faint trickle. High-speed time is no longer a currency source.

Award Formula Multiplier value
Overtake money floor(overtakes * overtakeMoneyMP) overtakeMoneyMP = 120
Near-miss money floor(nearMisses * totalNearMissMoneyMP) totalNearMissMoneyMP = 30
Distance money floor(distance * totalDistanceMoneyMP) totalDistanceMoneyMP = 40

The currency you earn is spent in the showroom to unlock the locked vehicles (prices range from ₵15,000 to ₵45,000; players start with 20,000 currency from initialMoney). The endless high score itself, bestScoreOvertake, is the maximum of your previous best and the run's score, persisted in FinishRace(). The scoring/risk fields overtakePoints, oncomingNearMissMultiplier, overtakeChainCap, passiveScoreRate, and headOnFrontalDot are all surfaced in the custom TO_Settings inspector (under its Score Multipliers and Overtake Scoring & Risk sections). See 12_EditorTools.md for the inspector layout and 14_APIReference.md for the TO_API and TO_Settings surface.

Who It Is For

Traffic Overtaker is aimed at two audiences. Reskinners want a finished, shippable arcade game they can rebrand — new car models, new road art, new UI skin, new audio — without rebuilding the gameplay; the project's template-driven scenes and centralized TO_Settings configuration make that practical, and the dedicated guide 10_ReskinningScenes.md walks through it. Arcade-racer developers want a clean, working reference for an input-level AI driver layered on a commercial vehicle-physics package (RCCP), a pooled traffic system, a curved-road treadmill, and a currency-and-customization storefront — all of which can be lifted or studied independently.

Whichever you are, the recommended path is: install and open the project (02_Installation.md), learn the folder layout (03_ProjectStructure.md), then dig into whichever subsystem you intend to change.

See Also