Web assets are .html, .htm, or .css files under ui/. The directory rule is
enforced: they are not accepted as gameplay assets elsewhere. Rustic structurally
validates the document and executes inline <script> content in the same bundled,
sandboxed JavaScript behavior runtime used by .js scripts. It does not embed a
browser renderer and does not replace the editor shell.
Create the file with the Explorer so the editor registers its Asset ID and scope. Attach it as a global, scene, or object component through the editor; never insert a path or source string into scene metadata.
<!doctype html>
<html>
<head>
<style>
/* Valid content, but not a rendered browser stylesheet in this release. */
body { margin: 0; }
</style>
</head>
<body>
<script>
globalThis.behavior = {
Start() {
rustic.log("info", "web behavior started");
},
Update(dt) {},
OnDestroy() {},
};
</script>
</body>
</html>Inline script blocks and project-relative <script src="..."> files are combined and
evaluated as one sandboxed JavaScript behavior. Linked files must remain inside the
play snapshot. A CSS-only asset has no callbacks and is therefore a valid no-op
behavior. Module imports, DOM queries, events, fetches, storage, and layout APIs are
not available.
Canonical callbacks are Start, FixedUpdate, Update, OnEnable, OnDisable,
and OnDestroy; snake-case spellings remain compatible. Collision callbacks are not
currently bound by the embedded Web/JavaScript adapter. Only methods actually present
on globalThis.behavior run.
Inline code receives rustic, Game, and instance exactly as described in
the JavaScript guide:
const [x, y, z] = rustic.get_translation();
rustic.set_translation(x, y + 1, z);
rustic.set_property("score", 10);
rustic.EditAttribute("Color", [1.0, 1.0, 1.0]);
const camera = Game.scene.Find("Room.Camera");
Game.setCurrentCamera(camera);
instance.add("Cube");
if (rustic.key("KeyW").held) {
rustic.log("info", "forward key held in Play");
}JavaScript mutations are applied in command order after the callback. Canonical
game.scene.Scene.ObjectPath target resolution flushes earlier queued commands
before resolving the live object, including renames and reparenting. Properties must
be declared and type-compatible. Scene lookup returns stable IDs; JavaScript
Game.scene.List() currently returns path strings. Instance operations are queued
and do not return the created ID.
The Play input limits also apply to inline JavaScript:
only held WASD, arrow, and Shift state is forwarded from the embedded Play viewport.
Inline code cannot call another script object. API 1.1 adds shared Events
and gameplay actions to inline JavaScript; see Shared gameplay actions.
Inline code has no DOM, filesystem, network, Node APIs, processes, environment variables, package loading, or editor/backend access. Source must be UTF-8 and no larger than 1 MiB. Syntax/structure is validated before Play or reload. A validation failure leaves the previous good instance running; a callback failure disables only the failing behavior. Use Web assets for lifecycle-driven UI logic or future-facing content organization, not for browser rendering in the current release.
See Edit scene objects for named-scene hierarchy calls, supported attributes, copyable examples, and native SDK calls to edit another object. Use your language's native call syntax and its current runtime limitations.
API 1.1 exposes shared-core easing, tweens, movement, skeletal/keyframe/procedural animation, timelines, timers, paths, cameras, physics, effects, audio and signals. See Shared gameplay actions for attachment, native call conventions, duration/speed options, callbacks, scene-clock controls and backend limits.
A missing linked script is skipped with a runtime warning for that play session. Remaining linked and inline scripts continue running. Restore the file, stop Play, and start Play again to load it. Missing files are not retried during the session.