How Bedrock Particles Work
Every particle effect in Bedrock is split into two distinct concepts: the emitter and the particles themselves. The emitter is the invisible source placed in the world or attached to an entity. It controls how many particles are created, when they spawn, and the initial shape or volume they spawn within. The particles are the individual 2D billboards that fly out from the emitter, each running its own movement, appearance, and lifetime logic.
Because particles are handled entirely by the client's rendering engine, they live in the Resource Pack under the RP/particles/ directory. The file name does not dictate the particle's identifier; instead, the game reads the identifier string declared inside the JSON file. However, keeping your file names matched to your identifiers is standard practice to keep large packs organized.
Particles rely heavily on Molang. Almost every numeric field in a particle definition—such as speed, size, UV coordinates, or color tint—accepts a Molang expression. This allows a single particle definition to have randomized speeds per particle, change size over its lifetime, or read variables passed down from the entity that spawned it.
Anatomy of a Particle File
A particle file begins with a format_version (commonly "1.10.0" for standard particles) and the particle_effect root object. Inside particle_effect, the file is divided into two sections: description and components. The description block assigns the unique namespace identifier and links the texture and material used to render the particle.
The basic_render_parameters object inside the description requires both a material and a texture path. The material dictates how the game handles transparency, blending, and lighting. The texture path points to an image file in your Resource Pack, relative to the pack root (without the file extension).
Below is a complete, minimal particle effect that spawns a single rising puff of smoke when triggered.
| Material Name | What it does | Notes |
|---|---|---|
| particles_opaque | Renders solid pixels with no transparency. | Fastest to render; good for solid debris or stone chips. |
| particles_alpha | Supports binary transparency (fully visible or fully invisible pixels). | Discards pixels below an alpha threshold; ideal for crisp pixel-art particles. |
| particles_blend | Supports smooth, partial transparency and alpha gradients. | Required for soft smoke, glowing orbs, or fading effects. |
| particles_add | Additive blending that brightens pixels behind the particle. | Best for fire, lasers, and magic sparks. |
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:magic_puff",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particle/particles"
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 15
},
"minecraft:emitter_lifetime_once": {
"active_time": 1.0
},
"minecraft:emitter_shape_point": {
"offset": [0, 0.5, 0],
"direction": ["math.random(-0.5, 0.5)", 1.0, "math.random(-0.5, 0.5)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.5, 1.5)"
},
"minecraft:particle_initial_speed": 2.0,
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 1.5, 0],
"linear_drag_coefficient": 2.5
},
"minecraft:particle_appearance_billboard": {
"size": [0.2, 0.2],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 128,
"texture_height": 128,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": {
"color": [0.6, 0.2, 0.9, 1.0]
}
}
}
}Core Emitter and Particle Components
Every functional particle effect requires at least five categories of components to actually appear in the world: emitter rate, emitter lifetime, emitter shape, particle lifetime, and particle appearance. If you omit any of these, the effect will either fail to spawn or spawn invisible points.
Emitter components all start with the prefix minecraft:emitter_. Rate components decide how particles enter the world: minecraft:emitter_rate_instant fires a burst all at once, while minecraft:emitter_rate_steady spawns a continuous stream at a set spawn_rate up to a max_particles cap. Lifetime components like minecraft:emitter_lifetime_once or minecraft:emitter_lifetime_looping control how long the emitter itself stays alive.
Particle components start with minecraft:particle_ and govern each spawned billboard individually. You must define how long a particle lives using minecraft:particle_lifetime_expression, and how it renders using minecraft:particle_appearance_billboard. If you want the particle to move, you pair minecraft:particle_initial_speed with an emitter direction and a motion component like minecraft:particle_motion_dynamic.
| Component | What it does | Notes |
|---|---|---|
| minecraft:emitter_rate_instant | Spawns a set number of particles immediately when the emitter activates. | Useful for explosions, hit impacts, and footsteps. |
| minecraft:emitter_rate_steady | Spawns particles continuously over time. | Requires spawn_rate (per second) and max_particles. |
| minecraft:emitter_shape_point | Spawns all particles from a single point offset. | Can also define the initial direction vector for the particles. |
| minecraft:emitter_shape_sphere | Spawns particles within or on the surface of a sphere. | Supports radius, surface_only, and inward/outward directions. |
| minecraft:particle_lifetime_expression | Controls when an individual particle is removed. | Uses max_lifetime (in seconds) or an expiration_expression. |
| minecraft:particle_motion_dynamic | Applies physics-like acceleration and drag each frame. | Used for gravity, rising smoke, or slowing down initial bursts. |
| minecraft:particle_appearance_billboard | Renders the 2D quad, setting its size, camera rotation, and texture UVs. | Mandatory for the particle to be visible. |
| minecraft:particle_appearance_lighting | Allows the particle to be tinted by world lighting (daylight and block light). | An empty object {}; without it, the particle glows in the dark. |
Built-in Particle Molang Variables
To animate particles over time without creating dozens of texture frames, Bedrock provides four built-in Molang variables inside every particle effect. Two belong to the emitter, and two belong to each individual particle.
variable.emitter_age tracks how many seconds have passed since the emitter started its current loop, while variable.emitter_lifetime holds the total active time of that loop. Meanwhile, variable.particle_age tracks how many seconds a specific particle has existed, and variable.particle_lifetime holds the max_lifetime assigned to that specific particle.
In addition, Bedrock provides four pre-calculated random numbers per particle: variable.particle_random_1 through variable.particle_random_4. Each holds a consistent float between 0.0 and 1.0 for the entire life of that particle. You should use these instead of calling math.random() inside components that evaluate every frame (like size or acceleration), otherwise the particle will jitter wildly on every tick.
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:shrinking_spark",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particle/particles"
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 20,
"max_particles": 50
},
"minecraft:emitter_lifetime_looping": {
"active_time": 2.0
},
"minecraft:emitter_shape_sphere": {
"radius": 0.5,
"direction": "outwards"
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "0.5 + variable.particle_random_1 * 0.5"
},
"minecraft:particle_initial_speed": 1.0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": [
"0.15 * (1.0 - (variable.particle_age / variable.particle_lifetime))",
"0.15 * (1.0 - (variable.particle_age / variable.particle_lifetime))"
],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 128,
"texture_height": 128,
"uv": [0, 16],
"uv_size": [8, 8]
}
}
}
}
}Spawning Particles in the World
The fastest way to test a custom particle in-game is with the /particle command. The syntax requires your custom identifier and a 3D coordinate. For example, running /particle wiki:magic_puff ~ ~1 ~ in chat or a command block will spawn the emitter one block above the executor's feet.
When building entities, you typically attach particles inside the client entity file (RP/entity/). In the description object, you map a short name to your particle's identifier under the particle_effects key. You can then trigger that short name from an animation timeline or an animation controller, optionally binding it to a specific bone locator from your geometry file.
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "wiki:custom_mage",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/custom_mage"
},
"geometry": {
"default": "geometry.custom_mage"
},
"particle_effects": {
"cast_spell": "wiki:magic_puff"
},
"animations": {
"casting": "animation.custom_mage.casting"
},
"scripts": {
"animate": [
"casting"
]
},
"render_controllers": ["controller.render.default"]
}
}
}Which versions this applies to
Applies to Minecraft Bedrock 1.10.0 and above. Custom particles are stable and do not require any experimental toggles.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Running /particle reports "Request to create wiki:magic_puff sent to all players", but nothing appears on screen. | The /particle command always reports success even if the identifier does not exist. Either the identifier is misspelled, the JSON has a syntax error, or you forgot to include minecraft:particle_appearance_billboard or a valid lifetime component. | Enable the Content Log in Creator Settings to check for JSON parsing errors, verify your identifier matches the description block, and confirm both emitter and particle lifetime components are present. |
| Particles render as pink and black missing-texture squares. | The texture path in basic_render_parameters does not match a real PNG file in your Resource Pack, or you included the .png file extension in the path. | Ensure the path starts with "textures/" and omit the file extension (for example, "textures/particle/my_spark"). |
| The entire texture sheet renders on every single particle instead of one icon. | The uv settings inside minecraft:particle_appearance_billboard are missing or the texture_width and texture_height do not match the actual pixel dimensions of your image. | Set texture_width and texture_height to match your image dimensions (or a normalized scale like 128x128 for the vanilla sheet) and specify uv and uv_size for the exact slice you want. |
| Particles spawned with initial_speed do not move at all. | Giving a particle an initial speed only sets its initial velocity; without a motion component, the engine does not update the particle's position on subsequent frames. | Add "minecraft:particle_motion_dynamic": {} to your components list so the particle's velocity is actually integrated each frame. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
