Game SDK
The API inside a game’s iframe. Where the JavaScript SDK is about the headset around a window, this one is about the session a game is part of: the shared room, the state everyone sees, and the actions your page submits to the server for judgement.The guide
Registering a game, writing the rules and the lobby lifecycle
Loading it
Copypublic/sdk/game.js out of the built RoadVR resource into your own game
and load it before your application. The source copy is at
ui/public/sdk/game.js, with game.d.ts beside it.
ui/index.html
This one is copied rather than loaded from
cfx-nui-roadvr, unlike the app
SDK. A game bundles its own build, and connect() negotiates the version
explicitly, so a copy that has fallen behind says so instead of failing
quietly.RoadVrGame.connect()
object
The connection:
state, on, send, pause, leave.game.state
room becomes null after departure or closure. me is the local
participant’s public RoadVR account tag.
Read
game.state once after connect() for the opening picture, then keep up
through the state event. After a reopened view this is the only correct
source — module globals from the previous iframe are gone.The Room snapshot
string
The six-letter code players read out to each other to join.
number
Increases on every lobby and game change. An older update can never replace a
newer accepted snapshot.
string
The account tag of the player who may start the game. It moves to another
present player if the host goes away.
string
A public RoadVR account tag — never a framework identifier and never a
FiveM source id.
object | false
The player’s saved Character Studio look, or
false when unavailable. See
the character module.object
Whatever your
onStart and onAction handlers put there. Public to every
participant.game.on()
on() returns its own unsubscribe function.
game.send()
Error whose code says why it did not.
string
required
The action name your
onAction handler switches on.object
Plain data, held to the same content limits as the state itself.
The error codes
On
stale, RoadVR asks for a fresh snapshot by itself — but the rejected
action is not replayed. Decide in your page whether the move still makes
sense against the new state, then send it again.A custom reason from your handler falls back to a generic message in the
shared lobby, so put player-facing wording in your own page.game.pause() and game.leave()
Pause is local: the other players carry on. Leave releases the seat
immediately, which is the difference between it and RoadVR’s Back to lobby
— that one closes the view but keeps membership.
The frame you are given
string
The host appends the player’s interface language to your page URL, or adds it
to the query string you already have. Use it for your own strings with English
as the fallback — RoadVR does not translate a game’s own text.
reserved
RoadVR’s controls sit there. Your iframe gets the rest. Size the renderer to
the iframe’s actual dimensions rather than to the viewport.
key
Opens RoadVR’s pause sheet from inside the iframe. Do not bind it yourself.
The character module
character.js renders the original RoadVR character, so a game does not need a
character system of its own.
{ root, head, update, dispose }
Accepts
false and falls back to the default appearance.void
Call from your render loop with elapsed seconds.
options takes
{ moving, reducedMotion, putt }; moving is a 0–1 intensity driving the
idle/walk blend.void
Call before replacing a look or removing a player. It removes the root and
releases the geometry and materials it owns.
Orientation
The model is Z-up, faces negative Y, and has its feet atZ = 0.
root to place the character. Pause your render loop with the
game and while the document is hidden.
The module also exports
normalizeAppearance, DEFAULT_APPEARANCE,
CHOICES, COLORS and PRESETS. CharacterAppearance describes the
version-1 hair, outfit, accessories, colours and body/face proportions in
character.d.ts, which game.d.ts re-exports — so keep the two declaration
files together when you copy them.What the Game SDK cannot do
Version 1 is one shared public state, judged on one server. There is no per-player private channel, no persistent score, no cross-server session, no distribution catalog and no shared world-space rendering — a game draws in its own iframe, not into the room around the player.Related
Custom Games
Registration, rules and the lobby
JavaScript SDK
The headset API, for apps and widgets
Client API
The Lua half
Discord Support
Questions about integrating