Particle components describe each single particle: how it starts, how it moves, how it looks and when it disappears. They sit in the components block of a particle file, next to the emitter components that spawn them.
New to particles? Your first particle builds a ruby sparkle from scratch and uses most of these.
What every particle needs
In practice every effect needs particle_lifetime_expression (or the particles never go away) and particle_appearance_billboard (or there is nothing to see). Everything else is optional and can be mixed freely.
Number fields accept a plain number or a Molang string. Inside them you can use variable.particle_age, variable.particle_lifetime and variable.particle_random_1 to _4 to give each particle its own personality.
Initial state
These are set once, when the particle is born.
| Component | What it does | Key fields |
|---|---|---|
minecraft:particle_initial_speed | How fast the particle starts moving | A number (blocks per second, along the emitter shape's direction), or an [x, y, z] speed |
minecraft:particle_initial_spin | The starting angle of the picture and how fast it turns | rotation: degrees (default 0). rotation_rate: degrees per second (default 0) |
minecraft:particle_initialization | Runs your own Molang for each particle, to set variables other fields read | per_update_expression: runs every update. per_render_expression: runs every time it is drawn |
Speed
"minecraft:particle_initial_speed": "math.random(1, 2)"With one number, the particle flies in the direction the emitter shape gave it. With three numbers, you set the velocity yourself, for example [0, 2, 0] for straight up. Leave the component out and particles start still.
Spin
"minecraft:particle_initial_spin": {
"rotation": "math.random(0, 360)",
"rotation_rate": "math.random(-90, 90)"
}Spin turns the flat picture around its centre, like a wheel. A random starting angle is the easiest way to stop a crowd of particles from looking like copies.
Your own variables
"minecraft:particle_initialization": {
"per_render_expression": "variable.twinkle = math.sin(variable.particle_age * 720) * 0.5 + 0.5;"
}Now variable.twinkle swings between 0 and 1 twice a second, and you can use it for size or colour. For a value that follows a shape over the whole life, a curve is often simpler.
Motion
These move the particle every frame, after it is born.
| Component | What it does | Key fields |
|---|---|---|
minecraft:particle_motion_dynamic | Real movement with forces: gravity, wind, air resistance, spin speed-up | linear_acceleration, linear_drag_coefficient, rotation_acceleration, rotation_drag_coefficient |
minecraft:particle_motion_parametric | You set the exact position each frame with Molang, ignoring forces | relative_position, direction, rotation |
minecraft:particle_motion_collision | Lets particles hit blocks: bounce, slide, stop or disappear | enabled, collision_radius, coefficient_of_restitution, collision_drag, expire_on_contact, events |
Dynamic
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, -9.8, 0],
"linear_drag_coefficient": 0.5,
"rotation_acceleration": 0,
"rotation_drag_coefficient": 0
}| Field | What it does |
|---|---|
linear_acceleration | A push every second, as [x, y, z] in blocks per second per second. [0, -9.8, 0] feels like falling. A positive y floats up like smoke |
linear_drag_coefficient | Air resistance. The faster the particle goes, the harder it slows down. 0 means none |
rotation_acceleration | Makes the spin speed up (or slow down with a negative value), in degrees per second per second |
rotation_drag_coefficient | Slows the spin down, so a spinning particle settles |
Dynamic motion works on the particle's speed, so it combines with particle_initial_speed: start fast, then let gravity and drag take over.
Parametric
"minecraft:particle_motion_parametric": {
"relative_position": [
"math.cos(variable.particle_age * 360) * 0.8",
"variable.particle_age",
"math.sin(variable.particle_age * 360) * 0.8"
]
}Here you skip physics and just say where the particle is, measured from the emitter. This example circles once a second while rising one block per second: a ruby spiral. direction and rotation can be set the same way.
Parametric needs a normal emitter
Parametric motion does not work for particles spawned by emitter_rate_manual. For effects attached to a mob, it only works when the emitter uses local space for its position.
Collision
"minecraft:particle_motion_collision": {
"collision_radius": 0.1,
"coefficient_of_restitution": 0.4,
"collision_drag": 2,
"events": { "event": "pop", "min_speed": 2 }
}Without this component, particles fly straight through blocks.
| Field | What it does |
|---|---|
enabled | Turns collision on or off. Can be Molang, checked every frame. Default on |
collision_radius | How big the particle is for hitting blocks. Must be half a block or less. Match it roughly to the billboard size |
coefficient_of_restitution | Bounciness. 0 stops dead, 1 bounces back to the same height, in between loses some height on every bounce |
collision_drag | Slows the particle while it touches a surface, in blocks per second. Makes it slide to a stop |
expire_on_contact | true removes the particle the moment it touches a block. Good for raindrops |
events | Fires one of your events when it hits something, for example a splash. One event object or a list. min_speed (at least 2 blocks per second) ignores soft touches |
Collision costs performance
Checking blocks for every particle is work for the game. Only add collision where you can see the difference, and keep max_particles low on those effects.
Appearance
These decide what the particle looks like on screen.
| Component | What it does | Key fields |
|---|---|---|
minecraft:particle_appearance_billboard | Draws the particle as a flat picture and decides its size, which way it faces and which part of the texture it shows | size, facing_camera_mode, direction, uv |
minecraft:particle_appearance_tinting | Colours the picture, with one colour or a gradient over time | color |
minecraft:particle_appearance_lighting | Makes the particle darker in dark places and brighter in light, like blocks | none: write {} |
Billboard
"minecraft:particle_appearance_billboard": {
"size": [0.1, 0.1],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 32,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
}size is [width, height] and is checked every frame, so Molang here can grow or shrink the particle. Each value is measured from the centre, so 0.5 makes a square one block wide.
facing_camera_mode decides which way the flat picture points:
| Mode | The picture |
|---|---|
lookat_xyz | Always faces the camera, but stays upright. The usual choice |
rotate_xyz | Lies flat against the screen, turning with the camera |
lookat_y / rotate_y | Faces the camera but only turns left and right, like a cut-out standing on the ground |
lookat_direction | Faces the camera while lining up with the particle's direction. Good for streaks |
direction_x / direction_y / direction_z | Points the picture's x side, y side or face along the particle's direction |
emitter_transform_xy / _xz / _yz | Lies flat in one plane of the emitter. _xz makes a flat decal on the ground |
The direction modes need to know which way the particle points. Set that with direction:
"direction": {
"mode": "derive_from_velocity",
"min_speed_threshold": 0.01
}derive_from_velocity uses the way the particle is moving, but only while it moves faster than min_speed_threshold. Use "mode": "custom_direction" with "custom_direction": [x, y, z] to set it yourself.
uv picks the part of the texture to show. texture_width and texture_height are the size of your PNG in pixels, then uv is the top left corner and uv_size the width and height of the part you want. The example above shows the first 8x8 frame of a 32x8 strip.
Flipbook animation
Put several frames side by side and the billboard can play them like a flipbook. Replace uv and uv_size with flipbook:
"uv": {
"texture_width": 32,
"texture_height": 8,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [8, 8],
"step_UV": [8, 0],
"max_frame": 4,
"stretch_to_lifetime": true,
"loop": false
}
}| Field | What it does |
|---|---|
base_UV | Top left corner of the first frame |
size_UV | Width and height of one frame |
step_UV | How far to move for the next frame. [8, 0] steps to the right |
max_frame | How many frames there are (the first is frame 1) |
frames_per_second | Playback speed |
stretch_to_lifetime | true ignores the speed and plays all frames exactly once over the particle's life |
loop | true starts again from the first frame after the last |
A 4-frame ruby sparkle that opens, shines and closes again looks far more alive than a single picture.
Tinting
"minecraft:particle_appearance_tinting": {
"color": [1, 0.15, 0.3, 1]
}The colour multiplies the texture, so draw particle textures in white or grey and let tinting add the colour. You can write a colour in any of these ways:
| Form | Example |
|---|---|
[r, g, b] or [r, g, b, a], each 0 to 1 | [1, 0.15, 0.3, 1] |
"#RRGGBB" | "#FF2650" |
"#AARRGGBB" (alpha first) | "#80FF2650" is half see-through |
| Molang in each slot | ["variable.tint.r", "variable.tint.g", "variable.tint.b", 1] |
To change colour over time, use a gradient. The colours are spread evenly, and interpolant picks where on the gradient the particle is right now:
"minecraft:particle_appearance_tinting": {
"color": {
"gradient": {
"0.0": "#FFFFFFFF",
"0.3": "#FFFF2650",
"1.0": "#00600018"
},
"interpolant": "variable.particle_age / variable.particle_lifetime"
}
}Written as an object like this, each colour sits at the point you name. A plain list spreads them evenly from 0 to 1 instead. This sparkle flashes white, turns ruby red early on, then slowly fades out.
Alpha needs the right material
Half see-through colours only show with the particles_blend or particles_add material. With particles_alpha, a pixel is either fully shown or fully hidden.
Lighting
"minecraft:particle_appearance_lighting": {}With this, particles look darker in caves and at night, so they fit in with the world. Leave it out for things that should glow in the dark: magic, fire, our ruby sparkle.
Lifetime
These decide when a particle disappears.
| Component | What it does | Key fields |
|---|---|---|
minecraft:particle_lifetime_expression | The main lifetime: a fixed time, or a Molang test checked every frame | max_lifetime, expiration_expression |
minecraft:particle_lifetime_events | Fires your events at moments in each particle's life | creation_event, expiration_event, timeline |
minecraft:particle_kill_plane | Removes particles that cross an invisible flat surface | [A, B, C, D] |
minecraft:particle_expire_if_in_blocks | Removes particles that are inside any of the listed blocks | A list of block names |
minecraft:particle_expire_if_not_in_blocks | Removes particles that leave the listed blocks | A list of block names |
Lifetime expression
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.8, 1.5)"
}max_lifetimeis the life in seconds, picked once when the particle is born.expiration_expressionis checked every frame. When it is not 0, the particle disappears. For example"variable.particle_age > 1 && query.is_in_water"could end it early.
You can use both together: the particle disappears at whichever comes first.
Lifetime events
"minecraft:particle_lifetime_events": {
"creation_event": "flash",
"expiration_event": "pop",
"timeline": {
"0.25": "twinkle"
}
}The names point at the events block of the same file, and each field takes one name or a list. Unlike the emitter version, these fire for every single particle, so a burst of 12 sparkles fires pop 12 times. See events for what an event can do.
Kill plane
"minecraft:particle_kill_plane": [0, 1, 0, 0.5]The four numbers describe a flat surface the maths way: all points where A*x + B*y + C*z + D = 0, measured from the emitter but lined up with the world. Particles that cross it disappear. [0, 1, 0, 0.5] is a floor half a block below the emitter. It is a cheap way to stop falling particles without collision.
In blocks and not in blocks
"minecraft:particle_expire_if_not_in_blocks": [
"minecraft:water",
"minecraft:flowing_water",
"minecraft:bubble_column"
]This is how bubbles pop when they reach the surface: they only live while inside water. Use particle_expire_if_in_blocks for the opposite, for example dust that vanishes the moment it drifts into water. Both work alongside particle_lifetime_expression.
A full particle
All four groups together. This is the particle side of a falling ruby shard that bounces and fades:
"minecraft:particle_initial_speed": "math.random(2, 3)",
"minecraft:particle_initial_spin": {
"rotation": "math.random(0, 360)",
"rotation_rate": 180
},
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, -9.8, 0],
"rotation_drag_coefficient": 1
},
"minecraft:particle_motion_collision": {
"collision_radius": 0.05,
"coefficient_of_restitution": 0.3,
"collision_drag": 4
},
"minecraft:particle_appearance_billboard": {
"size": [0.06, 0.06],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": {
"color": "#FFE0204A"
},
"minecraft:particle_appearance_lighting": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 2
}Give it an emitter from Emitter components, for example a burst of 8 from a small sphere, and it makes a great block breaking effect.