HomeGamesUpdatesPricingMethodology
Steam News4 January 20266mo ago

Fix Save Files

πŸ“Š Division of Responsibilities CRCarInfo.cs - Individual Car Tracking Purpose: Tracks per-car data and player-specific information βœ… Mileage tracking (total, session, race) βœ… Speed calculations (current, average) βœ… Lap

Full notes

Full City-Racing update

Read the full published notes in a cleaner layout. The original post stays linked below.

What changed

0 fixes3 additions5 changes0 removals
  • Events
  • Performance
  • Gameplay
changedCRRaceManager (fires events)
changedOnRaceStart event
changedEvent System:
changedΒ· CSV/TXT (CRCarInfo) = Detailed player performance analysis
changedThey communicate through events , method calls , and shared data structures (like FirstSecThird.RacerInfo and CRRaceManager.RacerData ).
addedRecommendation: Keep this architecture! It follows good separation of concerns. However, you could add a single centralized file manager if you want to consolidate the file I/O operations for consistency.

City-Racing changes

changedCRRaceManager (fires events)
changedOnRaceStart event
changedEvent System:
changedΒ· CSV/TXT (CRCarInfo) = Detailed player performance analysis
changedThey communicate through events , method calls , and shared data structures (like FirstSecThird.RacerInfo and CRRaceManager.RacerData ).

πŸ“Š Division of Responsibilities

  1. CRCarInfo.cs - Individual Car Tracking

Purpose: Tracks per-car data and player-specific information

  1. βœ… Mileage tracking (total, session, race)

  2. βœ… Speed calculations (current, average)

  3. βœ… Lap timing for individual car

  4. βœ… Waypoint navigation (arrow, beacon)

  5. βœ… Player GUI (diagnostics, countdown messages)

  6. βœ… File Creation:

Β· RaceData_{trackName}_{timestamp}.csv - Player's lap-by-lap data

Β· MileageReport_{trackName}_{timestamp}.txt - Player's mileage report

Β· car_mileage.json - Persistent mileage database

Β· race_history.json - Player's race history

  1. FirstSecThird.cs - Real-Time Race Position Tracking

Purpose: Tracks all racers during the active race

Β·βœ… Position calculations (1st, 2nd, 3rd, etc.)

Β·βœ… Comparative race data (all cars' laps, waypoints)

Β·βœ… Real-time sorting using Jobs System

Β·βœ… Race results display when race ends

Β·βœ… Best lap times tracking

Β·βœ… File Creation: NONE (purely runtime tracking)

  1. CRRaceManager.cs - Campaign & Scene Management

Purpose: Manages cross-scene race progression

  1. βœ… Persistent positions across multiple tracks

  2. βœ… Scene transitions and countdown coordination

  3. βœ… Campaign progress (which track, who's winning overall)

  4. βœ… Final standings across all races

  5. βœ… File Creation:

Β· race_save.json - Campaign save file with positions across scenes

---

πŸ”„ How They Work Together

During Race Start:

CRRaceManager (fires events)

↓

OnRaceStart event

↓

CRCarInfo (subscribes) β†’ Resets lap timer, mileage

FirstSecThird (subscribes) β†’ Starts position tracking

During Race:

CRCarInfo (each car)

β†’ Updates waypoints, lap times

β†’ Reports to FirstSecThird

↓

FirstSecThird

β†’ Calculates positions for ALL cars

β†’ Updates race manager

↓

CRRaceManager

β†’ Stores positions for next scene

When Player Finishes:

CRCarInfo (player)

β†’ Detects lap completion

β†’ Calls FinishRaceAndAllOtherRacers()

↓

FirstSecThird.ForceFinishAllRacers()

β†’ Finalizes all AI positions

β†’ Calls CRRaceManager.MarkRacerFinished()

↓

CRRaceManager

β†’ Updates campaign standings

β†’ Saves progress

β†’ Triggers scene transition

File Creation Summary:

CRCarInfo β†’ Creates CSV/TXT after EACH race (player stats)

FirstSecThird β†’ No files (runtime only)

CRRaceManager β†’ Saves JSON when positions change (campaign save)

βœ… Evidence They're Integrated:

  1. Event System:

// CRRaceManager fires:

CRRaceManager.OnRaceStart?.Invoke();

// CRCarInfo subscribes:

CRRaceManager.OnRaceStart += OnRaceManagerRaceStart;

  1. Cross-Script Communication:

// CRCarInfo talks to FirstSecThird:

FirstSecThird raceTracker = FindObjectOfType ();

firstSecThird.ForceFinishAllRacers();

// FirstSecThird talks to CRRaceManager:

raceManager.MarkRacerFinished(racerName, totalRaceTime);

  1. Data Synchronization:

// CRCarInfo syncs with CRRaceManager:

private void SyncSavedDataWithCurrentScene(FirstSecThird raceTracker, ...)

{

foreach (var savedRacer in raceManager.racers) {

var matchingSceneRacer = FindMatchingFirstSecThirdRacer(...);

matchingSceneRacer.position = savedRacer.currentPosition;

}

}

🎯 Why This Architecture Makes Sense:

ScriptScopeLifespanSaves Files?
CRCarInfoSingle CarPer Sceneβœ… Yes (player only)
FirstSecThirdAll CarsPer Scene❌ No
CRRaceManagerCampaignPersistentβœ… Yes (save game)

---

πŸ“ Bottom Line:

No, they're not redundant! Each has a specific role:

Β· CRCarInfo = "What's MY car doing?"

Β· FirstSecThird = "Where is EVERYONE right now?"

Β· CRRaceManager = "How's the CAMPAIGN going?"

The files they create serve different purposes:

Β· CSV/TXT (CRCarInfo) = Detailed player performance analysis

Β· JSON (CRRaceManager) = Campaign save/load system

They communicate through events, method calls, and shared data structures (like FirstSecThird.RacerInfo and CRRaceManager.RacerData).

Recommendation: Keep this architecture! It follows good separation of concerns. However, you could add a single centralized file manager if you want to consolidate the file I/O operations for consistency.

____________________________________________________________________________________

If FirstSecThird does not save a file what is laptimes.json for?

. Saving laptimes.json (Lines ~638-675)

  1. Loading laptimes.json (Lines ~677-707)

⏱️ What laptimes.json Contains

{

"bestLapTimes": [

{

"trackName": "CityRacing1",

"bestTime": 45.234

},

{

"trackName": "CityRacing2",

"bestTime": 52.891

}

],

"allTrackTimes": [

{

"trackName": "CityRacing1",

"lapTimes": [

{

"trackName": "CityRacing1",

"lapTime": 47.123,

"dateTime": "2026-01-03T19:27:18"

},

{

"trackName": "CityRacing1",

"lapTime": 45.234,

"dateTime": "2026-01-03T19:30:45"

}

]

}

]

}

πŸ”„ When Files Are Saved

FirstSecThird saves laptimes.json:

Β· On OnDestroy() (line ~236) - When the script is destroyed

Β· After displaying race results (line ~618) - In HideResultsAfterDelay()

private void OnDestroy()

{

// Clean up native arrays when object is destroyed

CleanupJobResources();

// Save lap times to persistent storage

SaveLapTimes(); // ← SAVES HERE

}

private System.Collections.IEnumerator HideResultsAfterDelay()

{

yield return new WaitForSeconds(raceResultsDuration);

showingResults = false;

// Save lap times before potentially leaving the scene

SaveLapTimes(); // ← SAVES HERE

}

πŸ“Š Summary - File Responsibilities

ScriptFile CreatedPurpose
CRCarInfoRaceData_{track}_{timestamp}.csvPlayer lap-by-lap CSV data
CRCarInfoMileageReport_{track}_{timestamp}.txtPlayer mileage report
CRCarInfocar_mileage.jsonPersistent mileage database
CRCarInforace_history.jsonPlayer race history
FirstSecThirdlaptimes.jsonBest lap times for ALL tracks
CRRaceManagerrace_progress.jsonCampaign save file

---

βœ… Conclusion

Your initial statement was incorrect - FirstSecThird.cs DOES save a file: laptimes.json

This file stores:

Β· Best lap times per track (for leaderboards)

Β· All lap times history (for statistics)

Β· Track-specific records (persistent across game sessions)

It's different from the CSV/TXT files that CRCarInfo creates because:

Β· CRCarInfo: Creates new timestamped files each race (detailed per-race reports)

Β· FirstSecThird: Updates one persistent file with best times (cumulative records)

The architecture makes sense:

Β· FirstSecThird = Historical best times (like a hall of fame)

Β· CRCarInfo = Individual race reports (like race receipts)

Β· CRRaceManager = Campaign progress (save game)

Source

Steam News / 4 January 2026

Open original post

Changelog.gg summarizes and formats this update. How we read updates.