A worked example, rendered from real sample data. Sign in to run the tool on your own input.
OnPlayerDied: playerId:int, cause:string
OnScoreChanged: score:int, delta:int
OnLevelComplete: levelId:string, timeSeconds:float
OnItemCollected: itemId:string
OnEnemySpawned: enemyId:string, spawnPoint:vector3export interface GameEventBusMap {
OnPlayerDied: { playerId: number; cause: string };
OnScoreChanged: { score: number; delta: number };
OnLevelComplete: { levelId: string; timeSeconds: number };
OnItemCollected: { itemId: string };
OnEnemySpawned: { enemyId: string; spawnPoint: Vector3 };
}
type EventKey = keyof GameEventBusMap;
type Handler<K extends EventKey> = (payload: GameEventBusMap[K]) => void;
export class GameEventBus {
private handlers = new Map<EventKey, Set<Handler<EventKey>>>();
on<K extends EventKey>(event: K, handler: Handler<K>): () => void {
let set = this.handlers.get(event);
if (!set) { set = new Set(); this.handlers.set(event, set); }
set.add(handler as Handler<EventKey>);
return () => this.off(event, handler);
}
once<K extends EventKey>(event: K, handler: Handler<K>): () => void {
const stop = this.on(event, (payload) => { stop(); handler(payload); });
return stop;
}
off<K extends EventKey>(event: K, handler: Handler<K>): void {
const set = this.handlers.get(event);
if (!set) return;
set.delete(handler as Handler<EventKey>);
if (set.size === 0) this.handlers.delete(event);
}
emit<K extends EventKey>(event: K, payload: GameEventBusMap[K]): void {
const set = this.handlers.get(event);
if (!set) return;
for (const handler of [...set]) (handler as Handler<K>)(payload);
}
clear(event?: EventKey): void {
if (event) this.handlers.delete(event); else this.handlers.clear();
}
}
export const gameEvents = new GameEventBus();
import { gameEvents } from "./GameEventBus";
…
Generate event bus / observer pattern boilerplate for Unity, Godot, or JS. Part of the DevTools Surf developer suite. Browse more tools in the Game Dev collection.