Privacy

Item clips

Animate the bones of a model part itself, such as a lid that opens or a flame that flickers, in step with the hand animation.

On this page

An item clip moves the bones of a model part’s own geometry: a lid that opens, a flame that flickers, a chain that sways. The hand clip moves your arm, and the item clip moves the item in it. This page is for pack makers who already have a model part and want it to come alive at the right moments.

You will make a lantern that sways and flickers while you hold it, opens its lid when you press the Inspect key, and burns low under water. Then you will line an item clip up with a hand clip and set up idle variants for different places.

Before you start

  • You need a model part: a definition, a geometry file and a texture. The lantern model part below gives you a small one to build in a few minutes. Model part definitions and Geometry and textures cover your own.
  • The parts that should move must be their own bones in the geometry, with names you can type. This page uses root, lid, flame and chain, and the lantern has them.
  • You need Punchy! 3.0 or newer, from Modrinth or CurseForge. The Studio path needs Punchy! Studio, from Modrinth or CurseForge. The Blockbench path needs Blockbench 5.
  • Resource packs live in the resourcepacks folder of your game folder. Resource packs shows how to turn one on.

How item clips work

Three things connect a clip to the item in your hand:

PartWhere it goesWhat it does
The clip fileassets/<namespace>/punchy/model_parts_items/animations/<name>.animation.jsonHolds the clips. Each clip says which bones move, when and by how much.
The animations listThe model part definitionNames the clip files to load.
The entriesmodelPartsAnimation in the same definitionEach entry says which clip plays for which moment.

An entry’s type is the moment. Punchy! asks for the same moments as it does for the hand, so an item clip starts when the matching hand action starts.

TypePlays when
idleNothing else is playing. This is the base clip of the item, and it keeps its own clock while another clip plays.
attackPunchy! starts the hand’s attack clip. The item needs an attack clip from a pack for the hand, and each swing starts the item clip again from the beginning.
miningYou hold the attack key on a block.
useItemThe hand’s use moment: a right click that uses the item, or a bow, crossbow, trident or spear being drawn.
useEat, useDrinkYou hold the use key on food (useEat) or on a drink (useDrink).
fishingrodYou cast or reel in a fishing rod. The entry’s throw names the clip of the cast and its pull the clip of the reel.
hand_in, hand_outThe item is equipped (hand_in) or put away (hand_out).
inspectYou press the Inspect key, I by default.
triggerableYou press a triggerable key of this item.
fallingYou are falling. An entry plays one clip for the whole fall: min_blocks on the entry has no effect here.
inWaterA candidate for idle. With no condition keys at all it matches everywhere, like a plain idle. With any condition key and no in_water, it also needs you to be touching water, but the type itself adds nothing to the score. Add in_water or inside_water to give it a water test that scores. See Idle variants.

Animation types and triggers explains exactly when the hand side of each moment starts. Types are matched without case, underscores, hyphens or spaces, so useItem, use_item and Use-Item are the same type.

When a moment has no entry, or its clip is missing, Punchy! plays the idle entry instead. With no idle either, the item stays in its rest pose.

The lantern model part

The lantern is a small model part: a base, a flame above it, a lid and a chain. If you already have a model part with bones named root, lid, flame and chain, skip to Make an item clip. Otherwise make the pack below. It has the three files every model part needs, and the clips come after.

The pack folder

  1. In resourcepacks, make a folder called My lantern pack.

  2. Inside it, make pack.mcmeta with the text below. The numbers are for Minecraft 26.3. Resource packs has the other versions.

    {
      "pack": {
        "description": "My lantern pack",
        "pack_format": 97,
        "min_format": 97,
        "max_format": 97
      }
    }
  3. Make the folders assets/minecraft/punchy/model_parts_items/definitions, geo and textures. The last two sit beside definitions.

The geometry

Save the geometry below in geo as my_lantern.geo.json. Every cube shows the whole 16 by 16 texture on each of its six faces. Sizes and pivots are in pixels, and 16 pixels make one block. The base is 6 wide and 2 high. The flame stands on it, 2 wide and 4 high, and scales up from its foot. The lid is a flat plate on top that pivots at one edge, and the chain stands on the lid and sways from its foot.

geo/my_lantern.geo.json
{
  "format_version": "1.12.0",
  "minecraft:geometry": [
    {
      "description": { "identifier": "geometry.my_lantern", "texture_width": 16, "texture_height": 16 },
      "bones": [
        {
          "name": "root",
          "pivot": [0, 0, 0],
          "cubes": [
            {
              "origin": [-3, 0, -3],
              "size": [6, 2, 6],
              "uv": {
                "north": { "uv": [0, 0], "uv_size": [16, 16] },
                "south": { "uv": [0, 0], "uv_size": [16, 16] },
                "east": { "uv": [0, 0], "uv_size": [16, 16] },
                "west": { "uv": [0, 0], "uv_size": [16, 16] },
                "up": { "uv": [0, 0], "uv_size": [16, 16] },
                "down": { "uv": [0, 0], "uv_size": [16, 16] }
              }
            }
          ]
        },
        {
          "name": "flame",
          "parent": "root",
          "pivot": [0, 2, 0],
          "cubes": [
            {
              "origin": [-1, 2, -1],
              "size": [2, 4, 2],
              "uv": {
                "north": { "uv": [0, 0], "uv_size": [16, 16] },
                "south": { "uv": [0, 0], "uv_size": [16, 16] },
                "east": { "uv": [0, 0], "uv_size": [16, 16] },
                "west": { "uv": [0, 0], "uv_size": [16, 16] },
                "up": { "uv": [0, 0], "uv_size": [16, 16] },
                "down": { "uv": [0, 0], "uv_size": [16, 16] }
              }
            }
          ]
        },
        {
          "name": "lid",
          "parent": "root",
          "pivot": [0, 6, 3],
          "cubes": [
            {
              "origin": [-3, 6, -3],
              "size": [6, 1, 6],
              "uv": {
                "north": { "uv": [0, 0], "uv_size": [16, 16] },
                "south": { "uv": [0, 0], "uv_size": [16, 16] },
                "east": { "uv": [0, 0], "uv_size": [16, 16] },
                "west": { "uv": [0, 0], "uv_size": [16, 16] },
                "up": { "uv": [0, 0], "uv_size": [16, 16] },
                "down": { "uv": [0, 0], "uv_size": [16, 16] }
              }
            }
          ]
        },
        {
          "name": "chain",
          "parent": "root",
          "pivot": [0, 7, 0],
          "cubes": [
            {
              "origin": [-1, 7, -1],
              "size": [2, 4, 2],
              "uv": {
                "north": { "uv": [0, 0], "uv_size": [16, 16] },
                "south": { "uv": [0, 0], "uv_size": [16, 16] },
                "east": { "uv": [0, 0], "uv_size": [16, 16] },
                "west": { "uv": [0, 0], "uv_size": [16, 16] },
                "up": { "uv": [0, 0], "uv_size": [16, 16] },
                "down": { "uv": [0, 0], "uv_size": [16, 16] }
              }
            }
          ]
        }
      ]
    }
  ]
}

The texture and the definition

  1. In textures, save a 16 by 16 pixel PNG as my_lantern.png. In any image editor, make a new 16 by 16 image, fill every pixel with one orange such as #E8861C, and export it. Any other 16 by 16 picture works too.

  2. In definitions, save the text below as my_lantern.json. It says that the geometry replaces the lantern in your hand, painted with your texture.

    {
      "items": ["minecraft:lantern"],
      "geo": "minecraft:punchy/model_parts_items/geo/my_lantern.geo.json",
      "texture": "punchy/model_parts_items/textures/my_lantern"
    }
  3. In the game, open Options, then Resource Packs, and move My lantern pack to the selected list. Resource packs shows the screen.

Hold a lantern in first person. The small model replaces it, and nothing moves yet.

Make an item clip

You will make two clips for the lantern. lantern_idle loops: the flame pulses and the chain sways. lantern_open plays once on the Inspect key: the lid tilts open and closes. Both paths end with the same files, shown in The files you end up with.

The finished files also hold two water clips: lantern_sink lasts 0.8 seconds and plays once, and lantern_idle_water lasts 3 seconds and loops. You make them the same way, with the keys from the file in The files you end up with. Make them now, or leave their entry out until you reach Idle variants.

Tool

In Punchy! Studio

Punchy! Studio keys the clips on a timeline, writes the clip file for you, and adds the entries to the definition.

Add the idle clip

  1. Join a world, hold your item, and press F6 to open Punchy! Studio. If it opens in the Third Person perspective, pick First Person with the switch between the menus and the workspace tabs.
  2. Click Model in the tabs at the top.
  3. Open the lantern with File > Open Model Part… (Ctrl+O). Choose Resource Packs, select my_lantern in the list and press Open.
  4. Open the Animation tab in the Properties column and press Add Clip. A clip named idle appears under Item Clips in the Outliner, and Studio adds its clip file to the definition’s animations list.
  5. In the Item Clip panel, type lantern_idle in Name and 2 in Length, and choose Loop on the Loop row. The row offers Once, Loop and Hold.
  6. Select the flame bone in the Outliner and pick its Scale row in the timeline. Put the playhead on 0 and press I. Studio inserts a key with the value Punchy! plays there. Set its values in the key column to 1, 1 and 1. Add a key at 1 with 1.1, 1.25 and 1.1, and a key at 2 with 1, 1 and 1.
  7. Do the same for the chain bone’s Rotation row, with 0, 0 and -4 at 0, then 0, 0 and 4 at 1, then 0, 0 and -4 at 2. Press Space to play the clip on the stage.

Video coming soon

Keying the idle clip on the Model workspace timeline.

Studio shows each key’s value as a number or as a Molang expression, and it plays every key linearly. The Graph Editor (Ctrl+Tab) draws the curve Punchy! really plays.

Add the entry

  1. In the Animation tab, press Add Entry. Studio adds an entry of Type idle for the clip you have selected.
  2. Check that Clip on the entry says lantern_idle.

Add the clip that plays on inspect

  1. Press Add Clip again. Name it lantern_open, set Length to 1.2, and leave Loop on Once.
  2. Select the lid bone and key its Rotation at 0, 0.4, 0.8 and 1.2: closed, open, open, closed. The open keys are -70, 0 and 0, and the closed keys are 0, 0 and 0.
  3. Key the same bone’s Position at the same four times, with the Y value at 1 on the two open keys and 0 on the others. The lid lifts a little as it opens.
  4. Press Add Entry. Set Type to inspect and Clip to lantern_open.

Video coming soon

An entry that plays the lid clip on inspect.

See it, then export

  1. Choose View > Live Link with Punchy (Ctrl+L). The right view shows Punchy! drawing your unsaved model in your hand, held at the playhead. Hold the item to see it.
  2. To see the pose of the hand next to your clip, choose View > In Hand, then View > Arm Pose from Animation Workspace. The arm takes the pose of the clip open in the Animation workspace.
  3. Choose File > Export Model Part… (Ctrl+E), pick the resource pack, tick Activate the pack and play it now, and press Export.

The live link holds the model at the playhead. To watch an entry play on its own moment, export, then press the Inspect key in the world.

For the water entry, press Add Entry once more and set Type to idle, Clip to lantern_sink and Keep Looping to lantern_idle_water, then choose Yes on the Under Water row.

Video coming soon

Previewing with the live link, then exporting.

In Blockbench

Blockbench makes the keys and the clip file for the same geometry file. You key the bones on its timeline, export a Bedrock animation file, and add the clips to the definition by hand.

Open the model and key the clips

  1. In Blockbench, open my_lantern.geo.json from the geo folder of your pack. Press Animate, the mode tab at the top.
  2. In the Animations panel, press Add Animation. Type lantern_idle in Name, set Loop Mode to Loop, and press Confirm. Set Animation Length to 2.
  3. In the Outliner, select flame. In the Timeline panel, click the ruler at 0 and press the + beside Scale. Type 1, 1 and 1 in the Keyframe panel.
  4. Add scale keys at 1 (1.1, 1.25, 1.1) and at 2 (1, 1, 1). Key the chain bone’s Rotation the same way, with -4 and 4 degrees around Z.
  5. Press Add Animation again for lantern_open. Keep Loop Mode on Play Once and set Animation Length to 1.2. Key the lid rotation at 0, 0.4, 0.8 and 1.2: closed, open, open, closed. Then add Position keys on lid at the same four times: 0, 1, 0 (X, Y, Z) on the two open keys and 0, 0, 0 on the others.

Video coming soon

Keying the lid in the Timeline panel.

Export the clips

  1. Choose Animation > Export Animations….
  2. In Select Animations to Export, tick lantern_idle and lantern_open, and press Confirm.
  3. Save the file as my_lantern.animation.json in resourcepacks/My lantern pack/assets/minecraft/punchy/model_parts_items/animations/. Make the folders in the save window if they do not exist yet.

Blockbench writes the file in the same shape as the example below. The numbers are in Bedrock’s own axes, which Punchy! converts when it loads the clip. Work in Blockbench and export again after a change, and do not copy numbers into the file by hand.

Make lantern_sink and lantern_idle_water the same way if you want the water entry. Then add the animations list and the entries to definitions/my_lantern.json, as shown in the next section.

The files you end up with

Here is the finished pack. The geometry, texture and pack.mcmeta are the ones you made in The lantern model part. Studio writes the same kinds of files, with its own file names.

My lantern pack/
  pack.mcmeta
  assets/minecraft/punchy/model_parts_items/
    definitions/my_lantern.json
    geo/my_lantern.geo.json
    textures/my_lantern.png
    animations/my_lantern.animation.json

The definition now names the clip file and lists the entries. Replace the starting definitions/my_lantern.json with it:

{
  "items": ["minecraft:lantern"],
  "geo": "minecraft:punchy/model_parts_items/geo/my_lantern.geo.json",
  "texture": "punchy/model_parts_items/textures/my_lantern",
  "animations": [
    "minecraft:punchy/model_parts_items/animations/my_lantern.animation.json"
  ],
  "modelPartsAnimation": [
    { "type": "idle", "animation": "lantern_idle" },
    { "type": "idle", "animation": "lantern_sink", "inside_water": true, "keep_looping": "lantern_idle_water" },
    { "type": "inspect", "animation": "lantern_open" }
  ]
}

The clip file holds all four clips:

{
  "format_version": "1.8.0",
  "animations": {
    "lantern_idle": {
      "loop": true,
      "animation_length": 2.0,
      "bones": {
        "flame": {
          "scale": {
            "0.0": [1, 1, 1],
            "1.0": [1.1, 1.25, 1.1],
            "2.0": [1, 1, 1]
          }
        },
        "chain": {
          "rotation": {
            "0.0": [0, 0, -4],
            "1.0": [0, 0, 4],
            "2.0": [0, 0, -4]
          }
        }
      }
    },
    "lantern_sink": {
      "animation_length": 0.8,
      "bones": {
        "flame": {
          "scale": {
            "0.0": [1, 1, 1],
            "0.8": [0.6, 0.6, 0.6]
          }
        }
      }
    },
    "lantern_idle_water": {
      "loop": true,
      "animation_length": 3.0,
      "bones": {
        "flame": {
          "scale": {
            "0.0": [0.6, 0.6, 0.6],
            "1.5": [0.45, 0.45, 0.45],
            "3.0": [0.6, 0.6, 0.6]
          }
        },
        "chain": {
          "rotation": {
            "0.0": [0, 0, -8],
            "1.5": [0, 0, 8],
            "3.0": [0, 0, -8]
          }
        }
      }
    },
    "lantern_open": {
      "animation_length": 1.2,
      "bones": {
        "lid": {
          "rotation": {
            "0.0": [0, 0, 0],
            "0.4": [-70, 0, 0],
            "0.8": [-70, 0, 0],
            "1.2": [0, 0, 0]
          },
          "position": {
            "0.0": [0, 0, 0],
            "0.4": [0, 1, 0],
            "0.8": [0, 1, 0],
            "1.2": [0, 0, 0]
          }
        }
      }
    }
  }
}

Reload your resources with F3+T, hold the lantern, and check three things:

  1. The flame pulses and the chain sways.
  2. I opens the lid for about a second. If it turns the wrong way on your model, flip the sign of its rotation.
  3. Dive under water: the flame shrinks over lantern_sink, then lantern_idle_water takes over and loops.

Video coming soon

The lantern in game: idle, inspect and under water.

Timing with the hand animation

An item clip and a hand clip are two separate clips with two clocks. They start on the same moment, and then each runs at its own speed. Getting them to line up is a matter of matching those speeds.

Both start together

When Punchy! starts the hand’s attack clip, it asks for the item’s attack clip in the same moment. The same goes for equip, put away, use, mining, falling and triggerable keys. A one-shot moment such as an attack, an inspect or a triggerable key blends in over about 0.15 seconds. A clip that takes over for a longer moment, such as mining, using or falling, blends in over about 0.4 seconds, and one idle replacing another takes 0.6 seconds. A longer moment that starts with nothing playing before it starts at once. A second swing starts the item’s attack clip over from time 0.

Match the speeds

Item clips always play at 1x. The player’s Animation Speed setting (5.5 by default) never applies to them. Hand clips are different: most of them follow that setting, unless the clip sets its own speed. A hand clip authored at 0.6 seconds therefore lasts about 0.11 seconds on the default setting, while an item clip of the same length lasts 0.6.

The safest way to line them up:

  1. Give the hand clip a fixed speed. In Punchy! Studio’s Animation workspace, set Speed to Fixed and pick a speed, such as 1x. Studio writes an anim_speed_ token into the clip. The In game line under Playback tells you how long the hand clip really lasts.
  2. Make the item clip last as long as the hand clip, at the same speed. At 1x that means the same length and nothing else to set.

Video coming soon

The hand clip in Studio. The Speed row reads Fixed and 1x, and the In game line gives its real length.

To run an item clip at another speed, put an anim_speed_ token on its timeline. If the hand clip is fixed at 2x, add a timeline key like this to the item clip (the braces only make the snippet a whole JSON object):

{
  "timeline": { "0.0": "anim_speed_2" }
}

The number runs from 0.5 to 5.5. The last token at or before the current time wins, so a later token changes the speed partway through the clip. In Studio, double-click the Speed lane of the item clip’s timeline to place one.

Some hand clips already play at their authored length, so an item clip at its default speed matches them: the equip and put away clips (hand_in and hand_out), the eating and drinking clips (use_eat and use_drink), and the bow, crossbow, shield and trident clips.

Fire a particle at a moment of the clip

An emitter in the definition can fire when an item clip reaches a time. Name the clip and the time in on_animation. This is the particle key of the definition, shown on its own:

{
  "particle": [
    {
      "type": "minecraft:flame",
      "bone": "lid",
      "count": 6,
      "velocity": [0, 0.04, 0],
      "on_animation": { "name": "lantern_open", "timecode": 0.4 }
    }
  ]
}

The puff of flame appears when lantern_open passes 0.4 seconds, the moment the lid is fully open. A time of 0 fires only when a looping clip wraps, never on the first start, so use a time above 0. Particles covers every emitter key.

Play a sound at a moment of the clip

Item clips take sound_effects the same way hand clips do, with the same two files, the .ogg and its event in sounds.json. A sound at time 0.0 plays when the clip starts. Animation reference explains the files.

{
  "animations": {
    "lantern_open": {
      "animation_length": 1.2,
      "sound_effects": { "0.0": "lantern_creak" }
    }
  }
}

Idle variants

You can have several idle entries on one item and let the world pick between them. Punchy! chooses the most specific entry that matches right now:

  • Every condition an entry has adds to its score: inside_water counts 3, in_water counts 2, and each of block_detection, weather_detection, time_detection and biome_detection counts 1.
  • Any entry with a score beats every entry with none. The highest score wins.
  • On equal scores, the entry that comes first in the file wins. Plain entries with no condition also go by file order.
{
  "modelPartsAnimation": [
    { "type": "idle", "animation": "lantern_idle" },
    { "type": "idle", "animation": "lantern_idle_rain", "weather_detection": { "raining": true } },
    { "type": "idle", "animation": "lantern_idle_night", "time_detection": { "min": 13000, "max": 23000 } },
    { "type": "idle", "animation": "lantern_sink", "inside_water": true, "keep_looping": "lantern_idle_water" }
  ]
}

This is the modelPartsAnimation list of the definition, with two more clips (lantern_idle_rain and lantern_idle_night) that you key the same way as the others. In rain, the rain idle plays. At night, the night idle plays. Rain at night is a tie of 1 and 1, so the rain idle wins because it comes first. Under water, the last entry wins with 3 over both. With none of these, the plain idle plays. Conditions explains the detection objects.

Some things to know about idle variants:

  • Switching. Moving from one idle clip to another blends over 0.6 seconds. Add "skip_blend_in": true to the new entry for a hard cut.
  • The idle clock. Punchy! keeps the idle clip’s time running while an action clip plays. When the action ends, the idle does not start from zero.
  • An intro and then a loop. keep_looping names a clip that loops after the entry’s own clip ends, for as long as the entry’s conditions still match. Above, lantern_sink plays once and lantern_idle_water then repeats while you stay under water.
  • A water entry written as a type. An entry of type inWater counts as an idle candidate. With no condition keys it matches everywhere, like a plain idle, and with any condition key and no in_water it also needs you to be touching water, with no score for it. Writing "type": "idle" with inside_water or in_water gives it the water test and the score.
  • Several items on one definition. Add items to an entry to limit it to some stacks, such as ["minecraft:soul_lantern"] or ["#minecraft:swords"]. An entry with no items applies to every item of the definition.
  • Quiet particles. disable_all_particles on an entry silences every emitter while it is active, which suits a flame that goes out under water.
  • Left and right hands. For a clip name an entry gives, Punchy! looks first for name_right or name_left for the arm that holds the item, then for the plain name. A _left clip played by the left arm is mirrored left to right.

Entry keys

Each object in modelPartsAnimation is an entry. The only key every entry needs is type.

Keys of a modelPartsAnimation entry
KeyTypeDefaultWhat it doesExample
typeRequiredstringThe moment: idle, attack, mining, useItem, useEat, useDrink, hand_in, hand_out, inspect, triggerable, falling or inWater. Matched without case, underscores, hyphens or spaces. An entry with no type never plays."idle"
animationstringThe clip to play, as named in the clip file. name and var_1 mean the same. When several are present, animation is read first, then name, then var_1."lantern_idle"
itemsstring listevery item of the definitionLimits the entry to stacks that match: item ids or # tags.["#minecraft:swords"]
keep_loopingstringA clip that loops after this entry's clip ends, while the entry's conditions still match. Give that clip "loop": true in the clip file."lantern_idle_water"
skip_blend_inbooleanfalseCuts to this clip with no blend.
skip_blend_outbooleanfalseWhen this entry is the one playing, cuts away from it with no blend when another entry takes over or the clip stops.
blend_from_current_originbooleanfalseStarts the blend from the pose on screen. blendFromCurrentOrigin, rebase_blend_in and rebaseBlendIn mean the same.
in_waterbooleanMust equal whether the player touches water. Scores 2.
inside_waterbooleanMust equal whether the player's eyes are under water. When true, the match keeps holding for a very short moment after you leave the water. Scores 3.
block_detectionobjectA block near the player. Scores 1. See Conditions.
weather_detectionobjectRain, thunder or clear sky. Scores 1. See Conditions.
time_detectionobjectA window in the day clock, 0 to 23999. Scores 1. See Conditions.
biome_detectionobjectA biome near the player. Scores 1. See Conditions.
disable_all_particlesbooleanfalseSilences every particle emitter of that hand while this entry is playing.
disable_physics_bonesstring listthe definition's own listBones taken out of the item's physics while this entry is playing, with their children. When the key is present, even as an empty list, it replaces the definition's list. disable_pendulum_bones means the same.["chain"]
disable_swim_animationbooleanfalseStops the swim pose of the hand that holds this item, whatever the world conditions of the entry.

Clip file keys

A clip file is a Bedrock animation file, the format Blockbench and Studio write. Punchy! reads only the animations object, so format_version is just a label.

Keys of an item clip
KeyTypeDefaultWhat it doesExample
animationsRequiredobjectClips by name. Every clip is also known as namespace:name. When two files give the same name, the later file in the animations list wins.
animation_lengthnumber0The length in seconds. A clip that loops needs a length above 0.2.0
loopboolean or stringfalsetrue repeats the clip. "hold_on_last_frame" stops on the last pose and keeps it. Set true on every clip that should repeat: idle clips, mining clips and the clip that keep_looping names.
bonesobjectThe bones to move, by name. A name that is not a bone of the geometry is skipped.
bones.<bone>.rotationlist or objectDegrees. A list of three numbers is one key at time 0. An object maps times in seconds to lists.
bones.<bone>.positionlist or objectOffset in model pixels, the unit of the geometry file. One pixel is one sixteenth of a block.
bones.<bone>.scalelist or object[1, 1, 1]A multiplier on each axis.
timelineobjectTokens at times, separated by semicolons: anim_speed_<number> (0.5 to 5.5), rotation_xyz or rot_xyz, and rotation_zyx or rot_zyx. Punchy! lowercases them.
sound_effectsobjectSound names at times. A value is the name as text, or an object with the name in effect.{ "0.5": { "effect": "lantern_creak" } }

A key value can be a list of three entries, such as [0, 0, -4], or an object holding that list in post, vector or pre. Punchy! reads one of the three, in that order. Each entry can be a number, a number written as text, or a Molang expression written as text, such as this flame flicker, shown as the bones object of a clip:

{
  "bones": {
    "flame": {
      "scale": { "0.0": [1, "1 + math.sin(query.anim_time * 360) * 0.1", 1] }
    }
  }
}

query.anim_time is the clip time in seconds. Anything Punchy! cannot read in a value counts as 0, with no message. Animation reference lists what the expressions can do.

Rotations turn the short way between two keys, so a step of more than 180 degrees goes the other way. Add a key in the middle to make a full turn. Every key is played linearly, and lerp_mode in a file is not read: use more keys for a curve.

The order Punchy! applies a rotation’s three axes is Z, then Y, then X. A clip whose name contains mace, trident or crossbow uses X, Y, Z instead. The rotation_xyz and rotation_zyx tokens set the order for the rest of the clip, whatever the name says.

Things that drop a whole file

These fail without a message:

  • A definition entry with a value of the wrong kind. A text where a list belongs ("items": "minecraft:lantern"), or a list where a single value belongs ("in_water": [true]), drops the whole definition. Studio’s Lint panel and the entry’s panel point at it. Entries that are not objects are skipped, and the rest are kept.
  • A clip that cannot be read. A key list with fewer than three numbers, or a key time in a rotation, position or scale object that is not a number, stops the file at that clip. The clips before it load, and the clips after it do not.
  • A missing clip file. An animations id that points at no file gives no clips. The ids are used exactly as written: write the folder and the .animation.json ending.

Why my clip does not play

  • The entry’s clip name has a typo. Punchy! falls back to the idle clip. With no idle, nothing moves. Studio’s Lint panel says “No clip named” and the name.
  • The bone name has a typo. A track for a bone that is not in the geometry is skipped. Bone names must match the geometry file.
  • The attack clip never starts. An attack entry plays when the hand’s attack clip starts. If no pack gives the item a hand attack clip, the item clip has nothing to follow. Use an idle or inspect entry to test first.
  • The model disappears while I eat, drink or draw a bow. While you use an item, Punchy! draws the vanilla item instead of your model, unless the definition has a useItem, useEat or useDrink entry, or a using state model. Add an entry for the use and the model stays.
  • The clip plays, but too fast or too slow against the hand. The hand clip is on the Animation Speed setting and the item clip is at 1x. Fix the hand clip’s speed or give the item clip an anim_speed_ token. See Match the speeds.
  • A looping clip does not loop. A clip with "loop": true and no animation_length, or a length of 0, never wraps back to the start. Give it a length above 0.
  • An idle clip plays once and stops. Set "loop": true in the clip file. The clip’s own loop decides, not its entry type.
  • Two entries seem to fight. Both match, and the one with the higher score wins. See Idle variants.
  • The clip is named like a mace, trident or crossbow clip. A name that contains one of those words reads rotations in X, Y, Z order. Rename the clip or add rot_zyx at time 0.
  • Nothing changes after an edit. Reload resources with F3+T. A file that does not parse is dropped as a whole, so check the JSON for a missing comma.

Last checked against the mod on 29 October 2026.