Particles are the small flat pictures you see everywhere in Minecraft: smoke from a campfire, hearts over a happy animal, bubbles under water. In this guide you will make your own: a ruby sparkle. It is a burst of little red glints that float up, twinkle and fade away.
You will learn what goes in a particle file, how to draw its texture, how to make it change over time and how to show it in game with a command, an animation or a script.
Resource pack only
Particles live completely in the resource pack. You do not need a behavior pack to make one, only to trigger it from a mob or a script. GodCraft writes the pack files and manifests for you: see Export and install.
The files
RP/
particles/
ruby_sparkle.json
ruby_dust.json
textures/
particle/
ruby_sparkle.pngEvery .json file in the particles folder is loaded by the game. The file name does not matter, but keeping it the same as the particle name makes things easy to find.
Emitters and particles
Before writing anything, it helps to know the two parts of every effect:
- The emitter is an invisible spawner. It decides how many particles appear, where they start and how long it keeps spawning.
- The particles are the little pictures. Each one decides how it moves, how it looks and when it disappears.
That is why particle components come in two families. Names that start with minecraft:emitter_ set up the spawner. Names that start with minecraft:particle_ set up each picture. You can write them in any order.
| Part of the file | What it holds |
|---|---|
description | The particle's name, plus its material and texture |
curves | Optional. Values that change over the particle's life |
events | Optional. Things that happen at certain moments, like spawning more particles |
components | Everything else: the emitter and particle settings |
Step 1: the texture
Draw an 8x8 PNG and save it as RP/textures/particle/ruby_sparkle.png. A small four-pointed star works well.
Draw it in white and light grey, not red. Later you will tint it with a colour, and a tint multiplies the pixels. White becomes any colour you like, but a red picture tinted blue would turn almost black.
Leave the background fully transparent. Particles are always flat squares, so the transparent pixels are what give them their shape.
Step 2: the description
Create the particle file and start with its name and look:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:ruby_sparkle",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particle/ruby_sparkle"
}
},
"components": {}
}
}identifieris the name you use to play the particle. Always give it your own namespace (herewiki:), so it can never clash with vanilla or another add-on.textureis the path to your PNG from the root of the resource pack, without.png.materialdecides how see-through pixels are drawn:
| Material | Pixels are | Good for |
|---|---|---|
particles_alpha | Either fully solid or fully invisible | Pixel art, like vanilla hearts and crits. The safe choice. |
particles_blend | Can be half see-through | Soft smoke, mist, fading dust |
particles_add | Added on top of what is behind them, so they glow | Magic, sparks, fire, light |
Our sparkle should glow, so change the material to particles_add once it works. Start with particles_alpha while testing, because it is the easiest to see.
Format version
1.10.0 is the version most add-on particles use, and every component on these pages works with it. Newer vanilla files use higher versions, but you do not need them for anything in this guide.
Step 3: the emitter
Now fill in components. First the spawner. We want one quick burst of 12 sparkles, spread around a small ball:
"minecraft:emitter_lifetime_once": {
"active_time": 0.5
},
"minecraft:emitter_rate_instant": {
"num_particles": 12
},
"minecraft:emitter_shape_sphere": {
"radius": 0.4,
"direction": "outwards"
},emitter_lifetime_onceruns the emitter one time and then removes it.emitter_rate_instantspawns all 12 particles in the same moment.emitter_shape_sphereplaces them inside a ball with a radius of 0.4 blocks, each one pointing away from the middle.
Every emitter needs one lifetime component and one rate component. Without them, nothing spawns. The shape is optional: leave it out and every particle starts at the exact centre.
Step 4: the particles
Next, tell each sparkle how to move and look. Add these after the emitter components:
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.6, 1.2)"
},
"minecraft:particle_initial_speed": 1.5,
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 1.2, 0],
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": [0.12, 0.12],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": {
"color": [1, 0.15, 0.3, 1]
}Here is what each one does:
- Lifetime. Each sparkle lives between 0.6 and 1.2 seconds.
math.randompicks a new number for every particle, so they do not all vanish at once. This is Molang, the small maths language Bedrock uses. - Speed. They shoot out at 1.5 blocks per second, in the direction the sphere gave them.
- Motion.
linear_accelerationpushes them up a little every second, so they float like embers.linear_drag_coefficientis air resistance: it slows the first burst down quickly. - Billboard. Every particle is a flat square.
sizeis half its width and height in blocks, so0.12makes a square about a quarter of a block wide.lookat_xyzkeeps it facing the player. - UV. This picks which part of the texture to show. Our texture is a single 8x8 picture, so we use all of it: start at
0, 0and take8, 8. - Tinting. Red, green, blue and alpha, each from 0 to 1.
[1, 0.15, 0.3, 1]is a ruby red. You can also write"#FF2650".
Save, load the world and type:
/particle wiki:ruby_sparkle ~ ~1 ~You should see a little red puff rise in front of you. If you see nothing, look at the table at the end of this page.
Step 5: make it twinkle with a curve
Right now each sparkle keeps the same size until it suddenly disappears. A curve fixes that. It is a value that follows a shape you draw with a few numbers.
Add a curves block next to description and components:
"curves": {
"variable.ruby_size": {
"type": "linear",
"input": "variable.particle_age / variable.particle_lifetime",
"nodes": [0.2, 1, 0.6, 0]
}
},- The name must start with
variable.. The game works out the curve for every particle, every frame, and stores the answer in that variable. inputis where along the curve we are. Age divided by lifetime goes from0(just born) to1(about to disappear).nodesare the values along the way, spread evenly from start to end. Our sparkle starts small (0.2), grows to full size (1), shrinks (0.6) and ends at nothing (0).typeis how the curve moves between nodes.lineardraws straight lines.catmull_romandbeziermake smooth bends, andbezier_chainlets you set each point and slope yourself.
Now use the variable in the billboard size:
"size": ["0.12 * variable.ruby_size", "0.12 * variable.ruby_size"],For a fade, the tint can change colour over the particle's life too. A gradient lists colours, and interpolant picks where we are between them:
"minecraft:particle_appearance_tinting": {
"color": {
"gradient": ["#FFFF8FA8", "#FFFF2650", "#00A0002A"],
"interpolant": "variable.particle_age / variable.particle_lifetime"
}
}Each colour here is written as #AARRGGBB, so the first two letters are alpha. The sparkle starts pale pink, turns ruby red and ends dark and invisible. With particles_add, dark colours fade into nothing, which looks lovely for glowing effects.
Step 6: add a pop with an event
Events make things happen at a certain moment. Let's leave a tiny puff of dust where each sparkle disappears.
First make the dust. It is a second, smaller effect:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:ruby_dust",
"basic_render_parameters": {
"material": "particles_add",
"texture": "textures/particle/ruby_sparkle"
}
},
"components": {
"minecraft:emitter_lifetime_once": { "active_time": 0.2 },
"minecraft:emitter_rate_instant": { "num_particles": 3 },
"minecraft:emitter_shape_point": {},
"minecraft:particle_initial_speed": 0.4,
"minecraft:particle_lifetime_expression": { "max_lifetime": 0.3 },
"minecraft:particle_appearance_billboard": {
"size": [0.04, 0.04],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": { "color": "#FF7A0F2E" }
}
}
}Then, back in ruby_sparkle.json, name an event and say what it does:
"events": {
"pop": {
"particle_effect": {
"effect": "wiki:ruby_dust",
"type": "emitter"
}
}
},Finally, fire the event when each sparkle runs out of life:
"minecraft:particle_lifetime_events": {
"expiration_event": "pop"
}An event can do more than spawn particles:
| Field in an event | What it does |
|---|---|
particle_effect | Starts another effect. type is emitter, emitter_bound, particle or particle_with_velocity |
sound_effect | Plays a sound, by its sound event name in event_name |
expression | Runs a Molang expression on the emitter |
log | Writes a message to the Content Log, handy for testing |
sequence | A list of events that all run, one after another |
randomize | A list of events where only one runs, picked by weight |
Do not let an effect spawn itself
If wiki:ruby_sparkle started wiki:ruby_sparkle from its own event, every particle would make more particles, forever. Always point events at a different, smaller effect.
The finished file
Here is the whole sparkle, with the glowing material switched on:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:ruby_sparkle",
"basic_render_parameters": {
"material": "particles_add",
"texture": "textures/particle/ruby_sparkle"
}
},
"curves": {
"variable.ruby_size": {
"type": "linear",
"input": "variable.particle_age / variable.particle_lifetime",
"nodes": [0.2, 1, 0.6, 0]
}
},
"events": {
"pop": {
"particle_effect": {
"effect": "wiki:ruby_dust",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_lifetime_once": {
"active_time": 0.5
},
"minecraft:emitter_rate_instant": {
"num_particles": 12
},
"minecraft:emitter_shape_sphere": {
"radius": 0.4,
"direction": "outwards"
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.6, 1.2)"
},
"minecraft:particle_lifetime_events": {
"expiration_event": "pop"
},
"minecraft:particle_initial_speed": 1.5,
"minecraft:particle_initial_spin": {
"rotation": "math.random(0, 360)",
"rotation_rate": 90
},
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 1.2, 0],
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": ["0.12 * variable.ruby_size", "0.12 * variable.ruby_size"],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"gradient": ["#FFFF8FA8", "#FFFF2650", "#00A0002A"],
"interpolant": "variable.particle_age / variable.particle_lifetime"
}
}
}
}
}We also slipped in particle_initial_spin: each sparkle starts at a random angle and turns slowly, so no two look the same.
Playing the particle
With a command
/particle plays an effect at a position. It needs cheats on.
/particle wiki:ruby_sparkle ~ ~1 ~You can put it in a function or a command block too. Use execute to play it on someone: /execute as @a at @s run particle wiki:ruby_sparkle ~ ~2 ~ shows a sparkle over every player's head.
From a mob's animation
A mob can play particles from its animations. This happens in the client entity file in the resource pack, so first see Your first custom mob if you have not made one yet.
1. Give the effect a short name in the client entity's description:
"particle_effects": {
"sparkle": "wiki:ruby_sparkle"
}2. Play it from an animation at a point in time. locator is optional: it is a named point on the model, and the effect follows it as the mob moves. Without one, it plays at the mob's feet.
"particle_effects": {
"0.5": {
"effect": "sparkle",
"locator": "head"
}
}3. Or play it from an animation controller state. It starts when the mob enters the state:
"particle_effects": [
{ "effect": "sparkle" }
]Each of these can also have a pre_effect_script: a bit of Molang that runs just before the effect starts. Use it to send values into the particle file, like a colour that depends on the mob.
Keep looping effects for mobs
When a mob plays an effect, the effect's emitter is attached to it. That is where emitter_lifetime_looping and emitter_lifetime_expression shine: a trail that follows a mob for as long as it walks, or glows while a Molang value is on.
From a script
Scripts can play particles anywhere, any time. Your behavior pack needs a script module in its manifest: Project setup shows how.
import { world } from "@minecraft/server";
world.afterEvents.itemUse.subscribe(({ source, itemStack }) => {
if (itemStack.typeId !== "wiki:ruby_wand") return;
const { x, y, z } = source.location;
source.dimension.spawnParticle("wiki:ruby_sparkle", { x, y: y + 1.5, z });
});Every time a player uses a wiki:ruby_wand item, a sparkle bursts above them. dimension.spawnParticle shows the effect to everyone nearby. player.spawnParticle works the same way, but only that one player sees it.
Scripts can also send values into the particle with a MolangVariableMap. This lets one particle file make sparkles in any colour:
import { MolangVariableMap } from "@minecraft/server";
// Inside the same itemUse handler as above:
const vars = new MolangVariableMap();
vars.setColorRGB("variable.tint", { red: 0.2, green: 0.6, blue: 1 });
source.dimension.spawnParticle("wiki:ruby_sparkle", { x, y: y + 1.5, z }, vars);In the particle file, read the three parts of the colour as variable.tint.r, variable.tint.g and variable.tint.b:
"minecraft:particle_appearance_tinting": {
"color": ["variable.tint.r", "variable.tint.g", "variable.tint.b", 1]
}Handy Molang variables
The game fills in these values for you. Use them in any Molang field.
| Variable | Value |
|---|---|
variable.particle_age | How long this particle has been alive, in seconds |
variable.particle_lifetime | How long this particle will live in total |
variable.particle_random_1 to _4 | Four random numbers from 0 to 1, different for every particle |
variable.emitter_age | How long the emitter has been running |
variable.emitter_lifetime | How long the emitter runs in total |
variable.emitter_random_1 to _4 | Four random numbers from 0 to 1, shared by the whole emitter |
variable.entity_scale | The size of the mob the effect is attached to |
variable.particle_random_1 is great for variety. For example "0.1 + variable.particle_random_1 * 0.05" gives every sparkle a slightly different size.
When something goes wrong
| What you see | Most likely cause |
|---|---|
| Nothing at all | The emitter has no lifetime or no rate component, or the identifier in the command does not match the file |
/particle says the effect does not exist | A typo in the JSON. Open the Content Log to find the broken line |
| A purple and black square | The texture path is wrong, or it ends in .png |
| The whole texture is squashed into one particle | The uv block is missing or texture_width and texture_height do not match the PNG |
| Black squares around each particle | The background of the PNG is not transparent, or you used particles_add with a dark picture |
| The particle is the wrong colour | The tint multiplies the texture. Draw the texture in white |
| It never stops | It uses emitter_lifetime_looping. For a one-off burst use emitter_lifetime_once |
More help is in Troubleshooting. Ready for more? Every emitter setting is on Emitter components, and every particle setting is on Particle components.