When I took over ISU Esports broadcast production, one of the things that bothered me most was the overlay situation. Most collegiate programs either use expensive licensed broadcast tools or run static graphics that don’t actually respond to what’s happening in the game. Neither felt right.
The Rocket League overlay I built changes that. It ingests live game data from Rocket League’s internal WebSocket API, parses it in real time, and drives a custom HTML/CSS/JS layer that reflects actual game state — score, time, boost, series count — while looking like something you’d see on an LCS broadcast.
The Data Source
Rocket League exposes game state through a local WebSocket when you run the game with the right launch flag. The data structure looks roughly like this:
{
"game": {
"time": 247,
"isOT": false,
"teams": [
{ "name": "ISU", "score": 2, "color": "blue" },
{ "name": "NIU", "score": 1, "color": "orange" }
]
},
"players": { ... }
}
The local Vite dev server runs a small Node.js proxy that connects to this socket and re-emits events over a second WebSocket that the overlay HTML can connect to from the browser. This two-hop approach keeps the browser overlay decoupled from the game’s internal API.
The Overlay Layer
The HTML/CSS layer is straightforward — the complexity is in the state machine that decides when to show what. A few things need to happen:
- Scoreboard is always visible during play
- Goal scored triggers a full-screen animation, then returns to scoreboard
- Overtime gets a distinct visual treatment
- Warmup / intermission shows a different layout entirely
const STATE = {
IDLE: 'idle',
WARMUP: 'warmup',
PLAYING: 'playing',
GOAL: 'goal',
OT: 'overtime',
POST: 'post_game',
};
function transition(next) {
if (next === current) return;
document.body.dataset.state = next;
current = next;
}
The data-state attribute on <body> drives CSS animations — each state has its own set of classes that animate in and out. This keeps game logic and visual logic cleanly separated.
Integration with vMix
The browser source in vMix loads the overlay page from localhost:5173 while the Vite dev server is running. vMix composites the overlay on top of the game capture and adds GT Title graphics for player names and matchup information.
The result: a fully automated, responsive overlay that reacts to goals, overtime, and game end without a human touching a button.
The first time it worked end-to-end during a live match was one of the best feelings I’ve had working on this program. No one in the audience knew it was a custom-built system running off a laptop under the broadcast desk.
What I’d Change
The main limitation is fragility: Rocket League’s internal WebSocket isn’t a documented API, and it can break with patches. A more robust solution would use an officially supported plugin or a dedicated server-side relay with persistent reconnection logic.
The state machine also has some rough edges around series tracking — right now series score is maintained manually by the operator, which could be automated.
Both of these are on the list for the ESPN broadcast.
The overlay was built for and used in ISU Esports home matches during the 2024–2025 season. The 2026 MVC Championship production will use an evolved version of the same architecture.