Browser Checks

Essential browser checks before publishing. These cover HTML5 and WebAssembly (Unity/Godot).


Supported Browsers

Isolation (COOP/COEP) & Engines

For Unity/Godot (WebAssembly + threads/SharedArrayBuffer), check Strict Isolation in the game form. The game will be served under https://games.voidrush.com/iso/<slug>/… with the headers: Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp. Avoid any non-CORS CDN resources (COEP will block them).

Capability Detection (Ready-to-Use Snippet)

Run this early (before heavy loading) to display a clear help message if a core feature is missing.

function detectCapabilities() {
  const canvas = document.createElement('canvas');
  const webgl2 = !!canvas.getContext('webgl2');
  const webgl1 = !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
  const wasm   = typeof WebAssembly === 'object';
  const sab    = typeof SharedArrayBuffer === 'function';
  const coi    = self.crossOriginIsolated === true; // true if COOP/COEP active
  const audio  = !!(window.AudioContext || window.webkitAudioContext);
  const idb    = !!window.indexedDB;
  const gamepad= 'getGamepads' in navigator;

  return { webgl2, webgl1, wasm, sab, coi, audio, idb, gamepad };
}

function minimalGuard({ requireIsolation=false, requireWebGL=true }) {
  const c = detectCapabilities();

  // WebGL
  if (requireWebGL && !c.webgl1) return { ok:false, reason:"WebGL unavailable" };

  // Unity/Godot (WASM + threads)
  if (requireIsolation) {
    if (!c.wasm)     return { ok:false, reason:"WebAssembly unavailable" };
    if (!c.sab)      return { ok:false, reason:"SharedArrayBuffer required" };
    if (!c.coi)      return { ok:false, reason:"Cross-origin isolated context required (COOP/COEP)" };
  }

  return { ok:true, reason:"OK" };
}
// Exemple usage:
// const g = minimalGuard({ requireIsolation:true, requireWebGL:true });
// if (!g.ok) showFatalOverlay(g.reason);

User Error Overlay

Show a readable message to players instead of a blank screen.

<div id="fatal-overlay" style="display:none;position:fixed;inset:0;background:#111;color:#fff;padding:24px;z-index:9999"></div>
<script>
  function showFatalOverlay(msg){
    const el = document.getElementById('fatal-overlay');
    el.innerHTML = "<h2>Cannot Launch Game</h2><p>"+msg+
      "</p><p>Try updating your browser, enabling WebGL/WebAssembly, or opening in Chrome/Edge/Firefox.</p>";
    el.style.display = 'block';
  }
</script>

Audio, Fullscreen & Controls

let audioCtx;
function unlockAudio(){
  if (!audioCtx) {
    const AC = window.AudioContext || window.webkitAudioContext;
    if (AC) audioCtx = new AC();
  }
  document.removeEventListener('pointerdown', unlockAudio);
}
document.addEventListener('pointerdown', unlockAudio, { once:true });

Storage & Persistence

async function storageCheck(){
  if (!('indexedDB' in window)) return false;
  try {
    const db = await new Promise((ok, ko) => {
      const r = indexedDB.open('vr_probe', 1);
      r.onupgradeneeded = ()=> r.result.createObjectStore('s');
      r.onsuccess = ()=> ok(r.result);
      r.onerror   = ()=> ko(r.error);
    });
    db.close();
    return true;
  } catch { return false; }
}

Performance & Stability

document.addEventListener('visibilitychange', () => {
  if (document.hidden) { window.game?.pause?.(); }
  else { window.game?.resume?.(); }
});

// Optional: detect "long tasks" (>50ms) to diagnose janks
if ('PerformanceObserver' in window) {
  try {
    new PerformanceObserver((list) => {
      for (const e of list.getEntries()) {
        if (e.duration > 80) console.warn('Long task', Math.round(e.duration)+'ms', e.name||'');
      }
    }).observe({ entryTypes: ['longtask'] });
  } catch {}
}

Network & CORS

Validation Checklist

  1. WebGL1+ OK, WebAssembly OK (if WASM engine), crossOriginIsolated = true for Unity/Godot.
  2. No recurring JS errors or blocked assets (network): the Network tab must not display 403/404/blocked-by-client on essential assets.
  3. Audio starts after first click; fullscreen accessible; keyboard/touch/gamepad controls functional.
  4. Storage (IndexedDB/LocalStorage) accessible or proper fallback.
  5. Reasonable load time (initial bundle < 50 MB, no looping long task freeze).

Quick Integration (Example)

Integrate these safeguards before your main boot:

(async () => {
  const guard = minimalGuard({ requireIsolation: /* true if Unity/Godot */ false, requireWebGL:true });
  if (!guard.ok) { showFatalOverlay(guard.reason); return; }

  if (!(await storageCheck())) console.warn('IndexedDB unavailable: save fallback (SDK Data Module recommended).');

  // Here: start your game
  // await startGame();
})();

Need examples of headers or embeds between voidrush.com and games.voidrush.com? Consult the Requirements → Basic launch section and the Resources → Assets page.