r/FlutterDev • u/Monkey-Chowder • 1h ago
Discussion Title: How I built a 20-player multiplayer mode for $0/month (to hide server costs from my wife)
Game dev isn't my day job. I build enterprise software by day, and indie games at night. Recently, I wanted to add a 20-player live race mode to my Flutter/Flame auto-runner, Trinity Rush.
The problem? I didn't want to burn hundreds of dollars a month running authoritative game servers. If my wife saw an AWS bill for a hobby project, I'd be sleeping on the couch.
So I faked real-time multiplayer using deterministic seeds and tiny input logs over Firebase Realtime Database.
- Zero server-side physics
Trinity Rush is a one-thumb party runner (your 3-hero party is your health bar; tap to jump, tap in mid-air for class skills). Because the physics are deterministic, I don't need a server calculating collisions. When a host starts a lobby (up to 20 players), they generate a single random course seed and a synchronized start timestamp (countdownLead = 3500ms). Every phone generates the exact same obstacle course locally.
- Streaming 12-byte tap events instead of X/Y coordinates
Streaming 60fps position vectors for 20 players would melt the Firebase free tier. Instead, I only record press/release timestamps in simulation milliseconds:
`{'t': tMs, 'k': press ? 1 : 0}`
Every 250ms, the client flushes that tiny batch to Firebase RTDB (with local disk persistence disabled so it stays pure in-memory).
- The 1.75-second Spectator and Public Broadcast illusion
When your party wipes, you drop into Spectator Mode to watch the survivors (and if the host toggles Public Broadcast in the lobby, anyone hanging out in the Tavern can tune in live). To keep network jitter from making other players teleport around, the spectator engine runs on a 1.75s delay buffer. Your phone reads the surviving players' tap logs and replays their exact inputs locally against the shared map seed.
It looks and feels like a chaotic 20-player live race (complete with live skull and confetti emotes), but under the hood it's just phones passing a few kilobytes of JSON back and forth. Total server cost for 1,000 active matches? $0.
If you want to test the netcode (or try to break it), the game is free on iOS and Android:
https://wono.dev/trinity-rush/get
Happy to answer any questions about how Flame handles deterministic fixed-timestep loops or how I structured the Firebase RTDB listeners!