- PlayerController: block WASD/jump callbacks when ChatUI is open - PlayerController: clic droit = unlock souris, clic gauche = re-lock (n'est plus un toggle) - PlayerController: ajoute ResetInputs() appelé à l'ouverture du chat - ChatUI: appelle ResetInputs() quand le panel s'ouvre pour éviter les touches collées - NetworkManager: seed les joueurs déjà présents dans la room à la connexion (les OnAdd Colyseus peuvent être manqués si l'état est décodé avant l'enregistrement des callbacks) - NetworkManager: garde anti-doublon dans OnPlayerAdd - NetworkManager: fallback sphere si remotePlayerPrefab est null Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ROLL'D
Browser-based marble MMO — multiplayer physics, real-time leaderboards, playable directly in your browser.
What is ROLL'D?
ROLL'D is a multiplayer marble game that runs entirely in the browser via Unity WebGL. Players control a physics-based ball in a shared 3D arena, competing for distance, speed, and style. The game features real-time synchronisation at 60 Hz, in-game chat, and persistent leaderboards.
No install. No account. Just open the page and roll.
Features
- Real-time multiplayer - up to 20 players per room, 60 Hz state sync via Colyseus WebSockets
- Physics-based gameplay - Unity Rigidbody, jump charge, gel pads (speed boosts), ball-to-ball bumps
- Room lobby - browse open rooms, create your own, choose your colour and name
- In-game chat - accessible in-game (T key) and on the dedicated website chat page
- Live leaderboards - distance, max speed, jumps, bumps, playtime, updated every 30 seconds
- Spectator camera - orbiting camera while in lobby or after disconnecting
- WebGL-native - no plugins, no downloads, runs in Chrome/Firefox/Edge
Architecture
rolld/
├── game/ # Unity 6 project (WebGL build)
│ └── Assets/Scripts/
│ ├── Network/ # Colyseus SDK integration, schema, lobby UI
│ ├── Stats/ # StatsTracker - periodic HTTP upload
│ └── UI/ # IMGUI in-game HUD, chat, keybinds
│
├── rolld_backend/game/ # Colyseus 0.17 game server (Node.js)
│ └── src/
│ ├── rooms/ # ArenaRoom - game state machine
│ ├── schema/ # Colyseus schema (Player + GameState)
│ ├── stats/ # StatsManager - JSON persistence
│ └── chat/ # ChatManager - in-memory history
│
└── frontend/ # React + Vite + Tailwind SPA
└── src/
├── pages/ # Home, Stats leaderboard, Chat
└── components/ # NavBar, GameCanvas (Unity embed)
Network flow
Browser
└── Unity WebGL (GameCanvas iframe)
└── Colyseus SDK (WebSocket wss://)
└── ArenaRoom (Node.js)
└── Broadcast state @60 Hz
Browser
└── React SPA
└── REST API (HTTPS)
├── GET /stats/leaderboard/:key
├── GET /chat/history?since=
└── POST /stats/update (from Unity every 30s)
Tech stack
| Layer | Technology |
|---|---|
| Game engine | Unity 6 LTS, C# |
| Multiplayer | Colyseus 0.17 (Node.js + WebSocket) |
| Frontend | React 19, Vite 5, Tailwind CSS 3 |
| Deployment | Docker, Coolify, nginx |
| Self-hosted | Proxmox LXC, Gitea, Traefik reverse proxy |
Running locally
Prerequisites
- Node.js 20+
- Unity 6000.x (for game builds only)
Game server
cd rolld_backend/game
npm install
npm run dev
Server starts on ws://localhost:2567.
Frontend
cd frontend
npm install
npm run dev
Open http://localhost:5173. The frontend points to the production game server by default - edit src/pages/StatsPage.jsx and src/components/GameCanvas.jsx to switch to localhost.
Unity (optional)
Open game/ in Unity 6. The server URL is hardcoded in Assets/Scripts/Network/NetworkManager.cs. Switch to wss://game.rolld.kerboul.me for prod or ws://localhost:2567 for local testing.
Controls
| Key | Action |
|---|---|
| WASD / Arrow keys | Move |
| Space (hold) | Charge jump |
| Space (release) | Jump |
| T | Open chat |
| Escape | Close chat |
| Tab | Show keybindings |
| Backtick (`) | Debug network info |
Live deployment
The stack runs on a self-hosted Proxmox homelab cluster. Coolify handles container orchestration and auto-deployment on git push. Traefik manages HTTPS termination.
Licence
MIT - do whatever you want with it.