Skip to content

Models and Animations

Piggo41 edited this page Oct 13, 2026 · 6 revisions

Bring a Blockbench model into BetaMoon

Create the model and clips in Blockbench, export their files, and connect them to a block or item through Lua. BetaMoon reads the supported exported data directly; installing the GeckoLib Minecraft mod is not required.

Create and export

  1. Create a Bedrock model, or use the GeckoLib Blockbench plugin. Give animated groups distinct, stable names such as root, head, and antenna.
  2. Create the texture and numeric animation keyframes. For a repeating idle motion, enable looping. Keep track of the exact exported clip name.
  3. Export geometry as robot.json, clips as robot.animation.json, and the texture as robot.png. Check the supported export versions below.
  4. Put the files beneath the instance's betamoon/scripts folder, for example in mymod/models, mymod/animations, and mymod/textures.

For modeling, UV editing, and animation authoring, see the Blockbench modeling and animation guide. For the plugin and export commands, see GeckoLib's Blockbench guide and export instructions. Those guides also describe features outside BetaMoon's current import subset; the table below defines what works here.

Supported exports

File Supported subset
.json Bedrock geometry format_version: "1.12.0"; exactly one geometry; named parented bones; multiple cubes/planes; bone/cube pivots and rotations; inflation; box UVs and per-face UVs; named material_instance bindings; named locators with optional rotation.
.animation.json Bedrock/GeckoLib-style format_version: "1.8.0"; named clips; numeric position/rotation/scale channels; numeric timestamps in seconds; linear, step, and Catmull-Rom interpolation; pre/post values; looping, one-shot, and hold-last-frame clips. GeckoLib easing supports linear.
.png Model texture. Uses the texture asset limits; retains its full dimensions.

Model .json files must contain the supported Bedrock geometry structure with named bones. Clips animate those bones. The filename does not determine the format; Java block/item model JSON is currently unsupported.

Models are limited to 128 bones and 2,048 cubes. Each JSON file is limited to 2 MiB. Animation files support up to 256 clips, 128 bone tracks per clip, and 20,000 keys in total, with times up to 3,600 seconds. Numeric constants must be finite and within ±1,000,000. Scale values must be nonnegative. Texture layout dimensions in geometry must be integers in 1–16,384.

Use whole-number cube sizes with box UVs. Use per-face UVs for fractional cube sizes. Mirrored box UVs are supported; for per-face mirroring, export flipped UV rectangles. Duplicate bones/locators, cyclic parents, missing animation parts, and unsupported fields produce errors that identify the offending field.

Meshes/skinning, UV rotation, expressions/Molang, animation controllers, sound/particle/timeline keys, non-linear GeckoLib easing, and locator scale-inheritance overrides are unsupported. Export cuboid geometry and numeric clips using the versions above. Keep your editable Blockbench project alongside the exported files for authoring.

Register the assets and use a model

This script assumes the exported clip is named animation.robot.wave:

name = "Modelled Robot Item"
version = "1.0.0"

function modInit()
    local model = betamoon.assets.models:add {
        key = "mymod:item/robot", path = "mymod/models/robot.json"
    }
    local clips = betamoon.assets.animations:add {
        key = "mymod:item/robot", path = "mymod/animations/robot.animation.json"
    }
    local texture = betamoon.assets.textures:add {
        key = "mymod:item/robot", path = "mymod/textures/robot.png"
    }

    betamoon.items:add {
        id = 29002, key = "mymod:item/robot", displayName = "Robot",
        appearance = {
            model = model, texture = texture,
            animation = { asset = clips, clip = "animation.robot.wave" }
        }
    }
end

Choose an unused item ID. The model appears in inventory, held, and dropped contexts. Install the BetaMoon Java agent before declaring model appearances. Inspect animation:getClips() if a clip name is unclear.

For a block, put the same appearance table on a block declaration, with an unused block ID and its gameplay material. Model visuals use 16 model units per block, with the origin centered horizontally at the block's bottom. Use render.variants[metadata].appearance to select models by block state or item subtype. Appearance changes do not change collision or selection shapes; configure those through the block shape API.

For complete files to inspect, start with the Desk Lamp model item, then the Clockwork Bird model item.

Add Lua motion

Use onPose to adjust named parts after the exported clip. Every evaluation starts from rest, so additions do not accumulate between frames:

local appearance = {
    model = "mymod:item/robot", texture = "mymod:item/robot",
    animation = { asset = "mymod:item/robot", clip = "animation.robot.wave" },
    onPose = function(ctx)
        ctx.pose:rotate("head", { x = 0, y = 15, z = 0 })
        if ctx.pose:hasPart("antenna") then
            ctx.pose:translate("antenna", {
                x = 0, y = math.sin(ctx.state.ageTicks * 0.1) * 0.5, z = 0
            })
        end
    end
}

Omit animation for a model driven entirely by Lua. Use the supplied time instead of counting render callbacks. The callback's pose writer expires when it returns. See pose methods and clip blending for complete controls.

Adjust display and refresh files

Set appearance.display.gui, held, ground, or block to adjust position, rotation, and scale for that context. Start with the defaults, then adjust the context that needs it. See appearance fields.

After exporting an updated file, call betamoon.assets:refresh() from a script callback. Registered models and clips also support texture-pack overrides. Preserve required part, locator, material, and clip names when replacing files. Watch the Scripts screen or console for fallback diagnostics.

Clone this wiki locally