Custom assets
Read this page as Markdown · All docs for AI agents
Accepted format
Upload a static, self-contained GLB 2.0. Textures and binary buffers must be embedded. External URLs, external buffers and unsupported extensions are rejected. Uploaded content must contain triangle meshes and valid references.
Accepted image sources are static PNG, JPEG or WebP; the converter fully decodes and re-encodes them. Maximum dimension is 2048 pixels per side, with a total decoded pixel budget of 4,194,304 per prop. Animated images, rigs, skinning, morph targets and prop animation are not supported.
Never upload .blend, .py, JavaScript, HTML, shaders, executables or archives as world assets. A GLB extension does not bypass validation; malformed files are rejected by structure and content.
Size limits
- At most 4 MB decimal per input GLB and converted output.
- At most 100 MB in the creator's entire uploaded model and background library, shared across their worlds.
- At most 512 files across models and panoramas. Prop uploads allow 60 attempts per rolling hour, and panoramas allow 12. Failed conversions count, and MCP and browser uploads share the same allowance.
- At most 100 MB total download for one world: its manifest, standard source assets and distinct uploaded assets. Repeating one model adds entity data but does not download the model again.
- A separate 500 MB estimated memory limit accounts for decoded geometry, textures, instances and collision data.
An asset can be small on disk but expensive in memory. Compressed textures expand when decoded. Every placed copy contributes to instance and collision memory and the placed-triangle budget, even though shared geometry downloads once.
Upload and use your asset
Use asset_upload through MCP, or send raw GLB bytes to POST /api/worlds/ai/assets/upload with your world token. The response includes the converted asset's hash, size, triangles, pixels and meshes.
Both upload methods send file contents directly to Cloudflare. Disposable offline converters sanitize and validate the file before storing the canonical result in R2. Betworld's application server authorizes your account or world token and records the validated hash and geometry budget; it does not receive the uploaded model bytes. Downloads come directly from R2 through the existing Betworld URLs.
Use asset: "upload:<hash>" in a prop entity, or the bare hash in a game-skin manifest. Download the returned asset URL to inspect the converted result. See the HTTP API for headers, examples and errors.
Practical modeling advice
Use a modest number of materials and mesh parts. Reuse shared props rather than uploading the same shape with slight color changes; entity tint can handle those. Merge fine details into one sensible mesh. Avoid giant textures for small objects. Bake complex appearance into textures rather than runtime shaders or scripts.
The official bridge centers custom models horizontally, places their bottom at zero and normalizes their maximum extent.
Asset lifecycle
Uploading adds a library asset; saving a world references it; publishing makes that layout available to players. Assets use immutable URLs. There is currently no public library-delete tool, so avoid uploading unused variants to conserve the 100 MB library allowance. Requesting an existing owner-scoped canonical asset does not add duplicate stored bytes.
Game skin assets
Replacement bodies, button shapes and playing surfaces use this same static GLB upload pipeline. Upload each distinct piece separately, then use its returned canonical hash in a skin manifest. Do not create a separate prop entity for a bound button. The runtime fits the piece to its reference socket, then applies v2 transforms to the visual and native interaction proxy; uploaded names/extras cannot choose an action. Every used hash counts toward world download/texture budgets, and every placed body/binding counts toward geometry and estimated memory budgets.
Background images
Upload panoramas separately from GLB props using World → Upload panorama, background_upload through MCP, or POST /api/worlds/ai/backgrounds/upload. Images use the same 100 MB library quota and have their own format and dimension limits. See terrain and backgrounds for the full reference.