Blockbench models#
A Blockbench .bbmodel in the place becomes a model you can animate, and its animations become
.anim clips. You can import one from a script, from the editor, or by dragging it into the scene.
Importing from a script#
scene.importBbmodel(path, parent?) turns a .bbmodel into a model and writes one .anim file per
Blockbench animation. It returns the model and a list of notes about anything it could not carry
over.
--!strict
local model, notes = scene.importBbmodel("res://models/fox.bbmodel")
for _, note in notes do
print(note)
end
local controller = model:firstChildOfClass("AnimationController") :: AnimationController
local animator = controller:firstChildOfClass("Animator") :: Animator
local animations = model:find("animations") :: Folder
local run = animator:loadAnimation(animations:find("run") :: Animation)
run:play()What it builds:
Model "fox" under parent, or world when left out
MeshPart "mesh" meshId = the .bbmodel, sized to the model, anchored
Bone ... one per Blockbench group, nested like the groups
AnimationController "animationController"
Animator "animator"
Folder "animations"
Animation "run" animationId = res://models/fox/run.animGroups and cubes#
- Each group becomes a
Boneat the group's pivot, turned by the group's rotation, and the cubes in the group are drawn rigidly with it. See Bones. - Blockbench's 16 units are one block. The model's origin sits at the
Model's position, so an entity model stands on it. TheMeshPartsits at the middle of the cubes. - Two groups with the same name are told apart by a number,
tailandtail2. - Cubes outside any group are drawn with the
MeshPartand never move. - Textures must be saved inside the
.bbmodel. One that only points at a file on disk is drawn blank.
Animations#
-
Each animation becomes a
.animfile next to the model, in a folder with the model's name. -
Keyframes become rotation, position and scale keys with their interpolation:
linear,catmullrom,bezierwith its handles, andstep. A keyframe with separate before and after values becomes two keys at the same time. -
The animation's
loopmode comes across as it is. -
Sound, particle and timeline keyframes become events:
- a sound fires
soundwith{ effect, file }; - a particle fires
particlewith{ effect, locator, file, script }; - a timeline keyframe fires
timelinewith its script as a string.
Connect with
track:getMarkerReachedSignal("sound"). - a sound fires
-
Molang is not run. A keyframe value that is a plain number, even written as text, comes across. Any other expression becomes 0 (1 for scale) and is listed in the notes.
-
anim_time_update,start_delay,loop_delayandblend_weightare listed in the notes when set, and otherwise ignored.
Axes and file versions#
The importer writes what Blockbench shows, so the clip looks the same in Moud:
- Angles are written in Blockbench's
zyxorder, and positions are in blocks. - A file saved by Blockbench 5 or later (
format_version5 and up) keeps its keyframes in the axes Blockbench shows, and they come across as they are. - Older files saved animated rotations with x and y turned the other way, and positions with x turned. The importer turns those back.
- Each clip also carries the model's
skeleton. It lets a bone's keys be added to its group's own rotation the way Blockbench adds them.
From Java#
The Java entry point, for tools such as the editor, is BbmodelImport.build(text, res, parent). It
returns the model, the .anim files to write and the notes. BbmodelImport.read(text, name) does
the conversion without making instances.
Playing an imported clip on a body#
A clip made on the player's shape plays straight on a body:
--!strict
local model, _ = scene.importBbmodel("res://models/emotes.bbmodel")
local animations = model:find("animations") :: Folder
local body = world:find("npc") :: Character
local dance = body.animator:loadAnimation(animations:find("dance") :: Animation)
dance:play(0.2)The model's own bones are not needed for this; the clip only reads its .anim file. Keep the
animations folder where every client can see it, or make your own Animation pointing at the same
file.
Group names are matched to body joints ignoring case, spaces, _, - and a leading biped:
| Group names | Body joint |
|---|---|
head |
head |
body, torso, chest, upperBody |
torso |
rightArm, armRight, rArm |
rightArm |
leftArm, armLeft, lArm |
leftArm |
rightLeg, legRight, rLeg |
rightLeg |
leftLeg, legLeft, lLeg |
leftLeg |
cape |
cape |
rightWing, wingRight, leftWing, wingLeft |
rightWing, leftWing |
So Blockbench's own names Head, Body and RightArm, Bedrock's rightArm and Java's
right_arm all land on the right joint. A model with at least three of these is marked
"rig": "player". A clip's retarget field overrides the guess, see
clip fields.
Blockbench players are usually nested: arms and head under the body, the body under a waist. A
body's joints are not; they all hang off its root. When a clip with a skeleton plays on a body,
each joint gets the whole movement its group made in the model, parents included. Turning Body in
the clip turns the arms and head with it and moves their pivots.
A body's limbs pivot where the player model's do, at the shoulders, neck and hips, which is where Blockbench's player templates put them.
For a rig with other names altogether, see Playing a clip on another rig.
Importing in the editor#
Right-click a .bbmodel in the Assets panel and choose Import animations..., or use Import
from Blockbench in the animation editor's clip menu. The dialog shows the
model on the left and three tabs:
- Bones lists every Blockbench group, its pivot, its number of cubes, and the body joint it plays
on. The guess comes from the group's name, as in the
table above. Pick another joint, or new bone to keep a
group off the body. A choice that differs from the guess is written into each clip's
retarget. - Animations has a box per Blockbench animation. Only the ticked ones are written. Molang keys are flagged, since they come across as numbers.
- Options sets the folder the clips go in,
animations/<model>/by default, and whether the model itself is added to the scene. Turn that off to write only the clips for a model you already have.
Import does what scene.importBbmodel does. It writes a .anim per
ticked animation, adds the model in front of the camera with a Bone per group, an
AnimationController and an Animator, as one undoable step, and lists the importer's notes. The
first clip then opens on the new model.
Dragging a .bbmodel into the scene#
A .bbmodel dragged into the scene arrives as a model you can animate: a Model with a Bone per
Blockbench group, an AnimationController and an Animator, and an Animation per Blockbench
animation. A .bbmodel with no groups stays a plain MeshPart.
A .bbmodel placed earlier as a plain MeshPart shows under Blockbench meshes in the editor's
rig picker. Picking it asks first, then turns it into such a model in
the same place, with its name, size, look and parent, as one undoable step.
Either way, each animation is written as a .anim in animations/<file>/:
- The folder is named after the
.bbmodelfile, not the instance:res://models/knight.bbmodelwrites toanimations/knight/, whatever the model is called. - Every model made from the same file shares that folder.
- A clip that is already there is kept, never overwritten.
- Each clip's
rigis the.bbmodel's path.
The step owns the clips it wrote. Undo removes them, and redo writes them again with the same content. A clip that was there before is never removed, and one you changed after it was written is kept on undo, with a line in Output saying so. Connected to a server, the clips are written and removed on the server too.
Exporting to Blockbench#
Export as .bbmodel in the animation editor's clip menu writes the open clip as a Blockbench
animation into <clip>.bbmodel in the folder you pick. The file is a copy of the .bbmodel the rig
was made from, or, for the player rig, a file with a group per bone.
Blockbench has no easings and no ping-pong, so easings are written as linear and ping-pong as loop. Calls and sounds become effect keyframes.
A Blockbench view model#
A .bbmodel can also be the arms you see in first person. See
a Blockbench view model.
