Browser games have a few quirks that are easy to miss. These best practices will help you avoid the most common issues.
Cross-origin isolation
Wavedash runs your game cross-origin isolated, so every backend, CDN, or script host your game talks to must send Cross-Origin-Resource-Policy: cross-origin and Access-Control-Allow-Origin: * on every response or the browser blocks it. See Cross-origin isolation for the full list of what's affected and how to diagnose a blocked request.
Shader stutter
WebGL and WebGPU shaders are compiled the first time they're drawn, which causes visible frame hitches. Warm them up during your loading screen by rendering every material off-screen before the game starts — in Unity call ShaderVariantCollection.WarmUp(), in Godot instantiate materials in a preload scene. See Shader stutter for the full cause, warmup strategies, and how to reproduce stutter during development (including the macOS Metal-cache gotcha).
The Escape key
Pressing Escape exits fullscreen and releases pointer lock before your game code sees the keypress. Don't use Escape as your pause key. Instead, listen for the browser events:
document.addEventListener("fullscreenchange", () => {
if (!document.fullscreenElement) game.pause();
});
document.addEventListener("pointerlockchange", () => {
if (!document.pointerLockElement) game.showMenu();
});
Audio on Safari
Safari won't play any audio until the user interacts with the page. You need to resume the audio context on the first click or tap:
document.addEventListener("click", () => {
if (audioContext.state === "suspended") audioContext.resume();
}, { once: true });
If you're using Unity, switch audio clips to Compressed in Memory instead of "Decompress on Load" — it uses dramatically less memory. Also use AAC/M4A instead of OGG since Safari doesn't support OGG natively.
Memory in long sessions
WebAssembly memory can only grow, never shrink. Games that load and unload assets over a long play session will fragment memory until the tab eventually crashes.
- Load assets in groups that get unloaded together
- Monitor memory with Chrome DevTools or Unity's Profiler
- Test 30+ minute sessions, not just quick launches
Before you launch
A quick checklist to run through before publishing:
- Title, description, cover art, preview video, and tags are set
- Production build uploaded with debug flags off
- Every backend and CDN your game calls sends
Cross-Origin-Resource-Policy: cross-originandAccess-Control-Allow-Origin: * - Tested on wavedash.com in Chrome, Firefox, and Safari
- SDK features work (leaderboards, achievements, saves, multiplayer)
- Audio plays correctly after first interaction
- Load time and frame rate are acceptable