Reusable Resources and Materials
A .world file places objects and owns scene settings. A
.material file describes a reusable appearance. A .prefab
groups an owned reusable entity hierarchy. A .physics file describes
reusable bodies, colliders and joints. A .particles file describes an authored group of emitters; see Authored particle effects. .environment and .postfx store world and camera appearance presets. .sound and .audiomix store source defaults and explicit mixer presets. These are V1 formats;
the development reader does not offer an older world schema or a migration mode.
All commands on this page require Extended mode.
See Saving and exporting resource projects for Save All, recovery journals, explicit export roots and live snapshot limits.
Shared definitions and local appearances
This complete material document describes blue Standard paint:
{
"format": "blitz3d.material",
"version": 1,
"id": "paint.blue",
"name": "Blue paint",
"assets": [],
"definition": {
"model": "standard",
"color": [0.15, 0.35, 0.8, 1],
"properties": {"metallic": 0, "roughness": 0.3}
}
}
Declare it in a world's assets array, then bind its alias on a
model component. A second object can override selected values:
{"id":"paint","kind":"material","loading":"required","source":"paint.material"}
{"type":"model","primitive":"sphere","materials":[
{"slot":0,"asset":"paint","overrides":{"color":[0.8,0.15,0.1,1],"properties":{"roughness":0.8}}}
]}
Overrides replace authored values on that instance. They do not modify the shared file or neighbouring objects. Removing an override reveals the shared value. Runtime brushes have independent parameters and texture transforms while sharing image and shader resources. Editing a brush with runtime commands does not rewrite the saved descriptor.
For a complete two-object scene, open shared-materials.world in the World Editor or run SharedMaterials.bb. The standalone resource example creates, edits, saves and loads a material through the public API.
Embedding, dependencies and paths
An asset uses exactly one of source or inline.
To embed a descriptor, put its complete resource document in inline
and omit source. The resource schema is identical in both forms.
Raw models, textures, heightmaps, sounds and shaders remain external files.
Each descriptor's assets array declares its own local aliases.
Dependency entries use id, kind, a source or inline
document, and optional import options. They do not have a loading
policy: preparation inherits the strongest policy required by their consumers.
Paths are relative to the declaring file; inline descendants use that file's
directory. Extraction and Save As rebase paths while preserving resource IDs.
An optional expectedId detects a replaced descriptor. Duplicate
identities from different files and dependency cycles fail validation.
Shader options.configuration must be omitted or empty. Select the
program in .b3shader and configure its material parameters in
.material. Nonempty configurations are rejected.
Material models and values
classic: colour, alpha, shininess, supported brush effects and texture slots0through7.standard: the native Standard material properties, alpha mode/cutoff and named texture roles.shader: exactly oneshader.assetalias orshader.builtinname, with typed float, int, four-component vector or colour parameters and named textures.
Colour values are linear RGBA floats from 0 to 1 with straight alpha. Rotations
use degrees. A texture binding stores asset, optional
frame, nonzero two-component scale, offset,
rotation, coordinates (0 or 1), blend (0 to 5)
and colorSpace. Standard baseColor, emissive, sheenColor and environment
roles use srgb; its data maps use linear. Classic/custom bindings use linear;
custom shader code controls further colour conversion. An explicit encoding must
match the role.
renderState selects blend (auto, opaque, alpha, multiply, add),
cull (auto, back, none) and depth (default, test-write, test, none). Shader
requirements still apply: incompatible explicit state fails validation.
MaterialPropertySchema reports the Standard property's component count, range
and defaults. MaterialShaderSchema reflects the prepared shader's
actual parameters and texture stages. Shader names are case-insensitive.
Numbered slots and changed model imports
Slot 0 applies to the whole model hierarchy. Positive slots address one-based surfaces in depth-first model/node order. All-surfaces and numbered bindings cannot overlap. Runtime validation checks that every addressed slot exists and has a compatible mapping at every LOD.
A positive slot on an imported model also requires modelRevision:
the lowercase SHA-256 value returned by WorldAssetImportRevision
for that ready model asset. It covers the importer contract, import options and
actual source inputs. Changes to geometry or textures invalidate this mapping;
moving an intact asset folder preserves it. A stale pin makes the next world
load fail with a reassign diagnostic. Existing worlds retain their old resources.
Slot 0 and primitive bindings do not use this field.
In the World Editor, open a model's Materials tab. Validate assignment prepares an isolated current model and material. Apply / Rebind records the reviewed mapping and makes the material required in one document transaction. To repair a changed import, review its current geometry in Assets and explicitly rebind. Validation does not lock source files indefinitely; a later edit can invalidate the saved pin on the next load.
Reusable physics and world-owned contexts
A .physics definition contains named physical materials, one or
more bodies, their shapes, and optional joints between bodies in the same
assembly. Body types are static, kinematic and
dynamic. Shapes are box, sphere, capsule, convex hull, triangle
mesh or heightmap terrain. Mesh and terrain colliders require static bodies.
Each body has at least one shape. A shape may name a physical material with
friction and restitution; density and sensor state are shape properties.
Distances and dimensions use metres, mass uses kilograms derived from
density, time uses seconds, and hinge angles and angular speeds use radians.
size gives the full box dimensions, sphere diameter, capsule
diameter and total height, or terrain width, height and depth. Shape offsets,
hull points, mesh points and joint anchors use the target entity's local space.
A body target may have a positive uniform world scale and rotation. Nonuniform
or sheared transforms fail loading. The loader scales dimensions, offsets and
authored geometry when it cooks the native collider. A body may declare
position and a unit rotation quaternion
[x,y,z,w]; these compose with its target's authored transform
before construction. Each body needs a distinct target entity.
Initial linearVelocity is a world-space metres-per-second
vector; angularVelocity is a world-space radians-per-second vector.
Distance lengths and slider limits/speeds scale with the first joint body's
target; hinge limits and speeds remain angular values.
{"id":"crate","kind":"physics","source":"crate.physics","loading":"required"}
{"id":"crate-entity","components":[{"type":"model","primitive":"cube"},
{"type":"physics","asset":"crate"}]}
A physics component places one assembly. Each body targets the component's
entity by default. For a multi-body assembly, targets maps body IDs
to entity references, for example {"arm":{"entity":"arm-visual"}}.
The world can also declare a physics-joint component to connect
bodies from independent assemblies. Its bodyA and bodyB
contain the physics component entity ID and local body ID. The example in
physics-showcase.world
shows a compound body, hinged assembly and cross-assembly distance joint.
The world owns one explicit physics context for its authored assemblies.
settings.physics.gravity sets its gravity (default
[0,-9.81,0]). After the world is ready, call
WorldPhysicsContext
to obtain the context, then StepPhysics context,1.0/60.0,4 from
your fixed-step loop. UpdateWorld still processes classic
collision and animation, but does not step this context. Code can retrieve
an authored body or joint using
WorldPhysicsBody
and WorldPhysicsJoint.
These handles belong to the world and become invalid when it is freed.
Loading constructs bodies and joints in a staging world. A missing target, invalid body reference, unsupported transform or native cooking failure fails the entire load; no incomplete world is published. In the World Editor, the Scene view draws native collider and joint overlays. Play physics steps its preview at a fixed 60 Hz; stopping rebuilds the preview from the saved authoring snapshot. The playable ReusablePhysics.bb sample demonstrates the same rules.
For a UI-only authoring path, follow Creating a physics scene from a new world to a saved floor, falling box and scene joint. The Physics definition window edits typed body state, shapes, physical materials, internal joints and exact geometry; Save validates a cooked candidate world. The Scene Physics pane attaches a single-body asset, places a multi-body assembly with a reviewed distinct target for each body, and offers Make Local or Save as New Physics for one selected consumer. Shared edits list affected consumers. Live DebugWorld sessions expose physics for inspection only.
Editing and saving
Use Edit / New Material or Edit Material in Assets. The inspector supports typed values, textures, live previews, Source / Repair, external Save, Save As / Extract and Embed in World. Embedded data reaches disk when the world is saved. Edit Shared Asset changes the shared definition. Override This Instance marks overridden values; Reset Override removes one override. Make Local creates a new resource ID and retargets the selected binding, preserving its model pin. Live debugging sessions currently disable material authoring.
Public document handles retain authored data independently of runtime worlds.
ResourceDocumentJson returns a caller-owned copy; editing it alone
does not change the document. Commit with ReplaceResourceDocumentSource
or ApplyResourceDocumentEdit, passing the current Long revision.
Invalid or stale edits leave the document unchanged. A typed transaction looks
like this, with revision set from ResourceDocumentRevision:
{"protocol":"blitz3d.resource-document-edit","version":1,"revision":0,
"operations":[{"op":"set-material-property","group":"properties","property":"roughness","value":0.4}]}
The other operations are set-name, replace-definition and replace-assets, each with a value. Property groups are properties, parameters, renderState and textures; omit group for colour, shininess, effects, alphaMode or alphaCutoff. The entire resulting document is validated before commit.
ValidateResourceDocument returns an owned JSON report containing
valid, errorCount and diagnostics. It does not return a Boolean. Repair mode
retains invalid source for editing, but invalid data cannot be saved as a valid
resource or instantiated. Save detects files changed since open. Save As to an
existing different target requires its observed SHA-256 digest. A child extraction
creates a new file and dirties its parent; it does not commit a multi-file save.
Free all returned JSON handles and resource documents when finished.
The material inspector prepares a fresh preview on Save, including after a
filename dialog, so changed shader and texture inputs are validated again.
External material saves use SaveResourceDocumentWithWorldEdit to
validate the proposed source against scene aliases and nested prefab bindings
before replacing the resource file and committing the in-memory world edit.
Rejected bindings, stale revisions and destination conflicts preserve both
documents and the destination. The world remains dirty until Save World.
This coordinates one resource file with one in-memory world edit; the general
multi-file Save All workflow is separate. Runtime import and shader validation
still require async preparation.
The inspector supplies its ready material preview to the commit operation.
Its actual source files must still match preparation and remain guarded during
the commit. Each affected instance's effective parameters are checked against
the prepared shader, including bindings inside prefabs. Embedded material and
instance-override edits use ApplyResourceDocumentWorldEdit for the
same validation, changing only the in-memory world. Programmatic callers may
omit the preview argument for authored-data validation alone; imported mesh
slot mappings still require a prepared model.
Preparing a resource
LoadResourceDocumentAsync snapshots the document into an ordinary
world. The document can be edited or freed immediately afterwards. Poll
WorldReady and service UpdateAsyncLoads; inspect
WorldLoadError on failure. Find the resource with alias
resource. For materials, WorldAssetMaterial returns an
independent brush. For prefabs, the placement root is named
instance. Release the snapshot world with FreeWorld.
Returned brushes remain usable after the world is freed.
Native prefabs
A prefab has one root and stable local entity and component IDs. Omitted component IDs default to their type; IDs on one entity must be unique. Labels and array order do not affect identity. Nested placements use the same prefab component as a world. Saving retains the placement and never saves its generated children alongside it.
Declare typed inputs in definition.inputs, for example
{"id":"paint","type":"asset","kind":"material","required":true}
or {"id":"target","type":"entity"}. Inputs are required by default.
Component inputs also require a kind, such as light.
On the placement, bind inputs.paint to {"asset":"blue"}
and inputs.target to {"entity":"anchor"}.
Nested definitions forward inputs with {"input":"paint"}.
Model components consume model inputs through assetInput; material
bindings use input instead of asset.
A part selector is {"instances":["nested-placement"],"entity":"body","component":"mesh"}.
Omit instances for the current scope and component for
an entity target. References inside a definition never search the outer scene.
Missing required inputs and invalid types fail before the world becomes ready.
For standalone preparation, a prefab with required inputs must be placed in a
world supplying those bindings; a resource-only snapshot cannot invent them.
A placement's overrides array contains target,
property and value. For example,
{"target":{"entity":"bulb","component":"light"},"property":"range","value":25}.
Entity overrides cover name, enabled, visible and position/rotation/scale.
Component overrides cover supported camera/light/collision settings, model
shadows, cullRange and lodTransition. A model material override uses
a material property patch and optional slot (zero by default).
Inner overrides apply before enclosing overrides. Structural changes require
editing the shared source or Make Local.
An attachment component supplies a typed target and
an optional bone name or hierarchy path. Its local transform is
relative to that target. Bone targets require an animated model and an existing,
unambiguous bone; validation finishes after model preparation. Parenting and
ownership cycles fail the load. Static model lods contains
{"asset":"low-mesh","distance":20} entries in strictly increasing
distance order; animated and morphed LOD meshes are rejected.
CopyEntity copies owned parts, remaps internal inputs and shares
immutable resources. External input targets remain borrowed. FreeEntity
and FreeWorld release owned parts even when they have been reparented.
They do not free borrowed input targets. EntityOwner,
CountOwnedEntities and GetOwnedEntity inspect ownership;
FindPrefabPart uses stable local identity. PrefabInputsBound
detects required targets that have since been freed. A copy with an invalid
required input, or an external binding into another world, is rejected.
In the World Editor, expand a prefab to inspect its owned parts, then use the Prefab inspector tab. Instance edits change the placement's bindings and overrides. Open shared source edits the containing descriptor and validates its consumers in the current world before saving. Make Local creates ordinary authored parts with fresh IDs and the effective overrides; Ctrl+Z undoes it. Save as New Prefab uses a new identity and retains shared media. External scene targets become typed inputs instead of leaking into the saved template. Shared-source disk saves are separate from the world's undo history.
From code, CreatePrefabDocument(world_document,entity_id$,file$)
captures a subtree as a dirty resource document; SaveResourceDocument
writes it. World edit operations entity.duplicate-subtree (id/newId)
and prefab.make-local (id) use ordinary revision-checked transactions.
Try the nested prefab scene and the complete authoring, copy and free example.
Validation and schemas
b3dworldc scene.world paint.material object.prefab validates
descriptors and their dependency graph. --no-files checks structure
without opening external dependencies. Runtime loading additionally checks
shader reflection and imported surface mappings.
The installation's world directory contains
world,
material,
prefab and
shared resource JSON Schemas.
The common schema is generated by b3dworldc --schema. Use the schemas
for structural authoring assistance and the native validator for byte limits,
duplicate keys/IDs, dependency and reference checks, hierarchy rules and
cross-property constraints. Descriptor closures allow 32 levels, 4096 documents
and 64 MiB of source text.