Skip to main content

Particle presets

A particle preset (.tparticles) is a named set of emitter settings that ParticleEmitter components play by guid. The same settings object is what a scene stores for an emitter with inline settings. This page shows a preset, the emitter fields, every built-in module with its fields and defaults, and how ranges, curves and gradients are written. ParticlePresetSerializer in src/Talesmith.VFX/Presets reads and writes the format.

Example​

Lantern Grove's campfire flames, shortened: modules that are switched off and some fields are left out.

samples/LanternGrove/assets/particles/campfire.tparticles
{
"version": 1,
"name": "Campfire",
"settings": {
"duration": 1,
"looping": true,
"prewarm": true,
"playOnStart": true,
"simulationSpace": "World",
"maxParticles": 300,
"culling": "Automatic",
"emission": {
"enabled": true,
"rateOverTime": 70,
"rateOverDistance": 0,
"bursts": []
},
"shape": {
"enabled": true,
"kind": "Circle",
"emitFrom": "Volume",
"radius": 14,
"direction": "Fixed",
"angle": -1.5707964,
"spread": 0.17453292
},
"initial": {
"lifetime": { "min": 0.5, "max": 0.85 },
"speed": { "min": 60, "max": 110 },
"size": { "min": 24, "max": 40 },
"rotation": { "min": 0, "max": 6.2831855 },
"color": { "from": "#FFFFFF", "to": "#FFFFFF" }
},
"forces": {
"enabled": true,
"acceleration": [0, -200],
"gravityScale": 0
},
"drag": { "enabled": true, "drag": 0.5 },
"colorOverLifetime": {
"enabled": true,
"color": {
"stops": [
{ "position": 0, "color": "#00FFE8A8" },
{ "position": 0.06, "color": "#70FFC860" },
{ "position": 0.5, "color": "#5AE5521A" },
{ "position": 1, "color": "#00500C00" }
]
}
},
"sizeOverLifetime": {
"enabled": true,
"size": {
"keys": [
{ "time": 0, "value": 0.8, "outTangent": 2 },
{ "time": 0.12, "value": 1 },
{ "time": 1, "value": 0.2, "inTangent": -0.9, "outTangent": -0.9 }
]
}
},
"renderer": {
"enabled": true,
"texture": null,
"builtInTexture": "Smoke",
"blend": "Additive",
"layer": 460,
"alignment": "Stretch",
"stretchSpeedScale": 0.004,
"stretchLengthScale": 0.85
},
"customModules": []
}
}
note

The sample presets were written by an earlier version of the serializer: their enum values are PascalCase ("Circle"), curves and gradients are wrapped in { "keys": [...] } and { "stops": [...] }, and vectors span several lines. The current serializer reads all of these. When you save a preset in the editor it writes camelCase enum values ("circle"), curves and gradients as plain lists, and vectors on one line.

Top-level fields​

FieldTypeDefaultMeaning
versioninteger1The format version. A newer version fails to load.
namestring"Particles"The name shown in the preset gallery.
settingsobjectdefaultsThe emitter settings below.

The file must be plain JSON: unlike most Talesmith files, comments are not allowed. Missing fields keep their defaults, so presets from older versions load in newer ones.

Emitter fields​

FieldTypeDefaultMeaning
durationnumber5Seconds in one cycle of emission; bursts are timed within it.
loopingbooleantrueStarts a new cycle when one ends; otherwise emission stops after one cycle.
prewarmbooleanfalseStarts looping effects as if a full cycle had already played.
playOnStartbooleantrueStarts playing as soon as the emitter is simulated.
startDelaynumber0Seconds to wait after playing starts before emitting.
simulationSpeednumber1Plays the effect faster or slower than game time.
simulationSpaceworld or localworldworld leaves particles behind when the emitter moves; local carries them along.
maxParticlesinteger1000The most particles this emitter keeps alive; emission pauses at the limit.
seedinteger0Makes the effect play the same way every time; 0 picks a new seed each time it plays.
cullingautomatic, alwaysSimulate or pauseWhenOffscreenautomaticWhat happens outside the camera's view. automatic pauses looping emitters and keeps one-shot emitters running so they finish on time.
customModulesarray[]Modules added by plugins, each { "type", "data" }; see Custom modules.

Modules​

Every built-in module is an object with an enabled flag and its own fields. Modules that are off still keep their values.

emission​

On by default.

FieldTypeDefaultMeaning
rateOverTimenumber10Particles emitted per second.
rateOverDistancenumber0Particles emitted per world unit the emitter moves, for trails.
burstsarray[]Bursts, each with time (seconds into the cycle, default 0), count (a range, default 10), cycles (default 1; 0 repeats until the cycle ends), interval (default 0.1 seconds) and probability (0 to 1, default 1).

shape​

On by default.

FieldTypeDefaultMeaning
kindpoint, line, rectangle, circle, cone, tile or polygonpointThe region particles are emitted from.
emitFromvolume or edgevolumeAnywhere inside the shape, or only on its outline.
radiusnumber16The radius of circles, and half the width of a cone's base.
innerRadiusnumber0Turns a circle into a ring.
arcnumber6.2831855The part of the circle that emits, in radians.
sizevector[32, 32]The size of rectangles and the length of lines.
coneAnglenumber0.5The full opening angle of a cone, in radians.
tilehexPointyTop, hexFlatTop or squarehexPointyTopThe grid whose cell shape a tile emitter uses.
cellSizevector[64, 64]The cell size of tile emitters.
pointsarray of vectors[]The corners of a polygon.
offsetvector[0, 0]Moves the shape from the emitter.
rotationnumber0Turns the shape, clockwise, in radians.
directionshape, fixed or randomfixedWhich way particles start moving: away from the shape, along angle, or any direction.
anglenumber-1.5707964The direction for fixed, in radians; the default points up.
spreadnumber0Turns each particle's direction by a random amount within this angle.
randomizePositionnumber0Moves each particle's start by up to this distance.

initial​

The values each particle starts with. Ranges pick a random value between min and max per particle.

FieldTypeDefaultMeaning
lifetimerange1 to 1.5Seconds each particle lives.
speedrange50 to 100Starting speed in world units per second, along the shape's direction.
sizerange8 to 16Starting width and height in world units.
rotationrange0Starting rotation, clockwise, in radians.
angularVelocityrange0Rotation per second, clockwise.
colorcolor rangewhiteStarting tint, multiplied by color over lifetime.
alignToDirectionbooleanfalseAdds the starting direction to the rotation, for sprites that point forward.
inheritVelocitynumber0How much of the emitter's own movement particles carry, 0 to 1.

The other modules​

These are off by default.

ModuleFields (defaults)
velocityOverLifetimelinear ([0, 0]), linearOverLifetime (curve, 1), orbital (0, radians per second, positive is clockwise), radial (0, world units per second), speedMultiplier (curve, 1)
forcesacceleration ([0, 0], world units per second squared), gravityScale (1; how strongly the scene's gravity pulls, negative rises)
dragdrag (1; the fraction of speed lost per second)
noisestrength (60), scale (96, the size of the swirls in world units), scrollSpeed (0.3), strengthOverLifetime (curve, 1)
colorOverLifetimecolor (gradient, white; birth on the left, death on the right)
sizeOverLifetimesize (curve, 1; a multiplier from birth at time 0 to death at time 1)
rotationOverLifetimeangularVelocity (3.1415927, radians per second), overLifetime (curve, 1)
textureSheetcolumns (4), rows (4), frameCount (0 uses every frame), mode (overLifetime or framesPerSecond), framesPerSecond (12), cycles (1), randomStartFrame (false)
collisiongroundPlane (true), groundOffset (64), groundAngle (0), worldColliders (false; also collides with physics colliders and tiles), layerMask (-1, every layer), bounce (0.4), friction (0.2), lifetimeLoss (0), killOnCollision (false), radiusScale (0.25), sendEvents (false; publishes ParticleCollision events)

renderer​

On by default.

FieldTypeDefaultMeaning
textureguid or nullnullThe image drawn for each particle; when empty, builtInTexture is used.
spritestring or nullnullA named sprite of the texture; null uses the whole image.
builtInTexturesoftCircle, glow, disc, smoke, sparkle, streak or squaresoftCircleThe image the engine generates when no texture is set.
blendalpha, additive, multiply or opaquealphaHow particles combine with what is behind them.
layerinteger400The render layer.
sortOrdernumber0Orders emitters on the same layer; higher draws in front.
sortByEmitterYbooleanfalseOrders emitters on the same layer by their Y position.
sortModenone, oldestInFront, youngestInFront or byYnoneWhich particles of this emitter are drawn in front.
alignmentrotation, velocity or stretchrotationHow particles are turned.
stretchSpeedScalenumber0.05Extra length per unit of speed when stretching.
stretchLengthScalenumber1The length multiplier when stretching.

Ranges, curves and gradients​

ValueWritten asAlso read from
Range{ "min": 0.5, "max": 0.85 }[0.5, 0.85], or one number for a constant
Color range{ "from": "#FFFFFF", "to": "#FFC860" }One color string for a constant
Curve[{ "time": 0, "value": 0.8, "outTangent": 2 }, { "time": 1, "value": 0.2 }]{ "keys": [...] }, or one number for a constant
Gradient[{ "position": 0, "color": "#00FFE8A8" }, { "position": 1, "color": "#00500C00" }]{ "stops": [...] }, or one color string for a solid gradient

Curve keys have a time and a value, both required, and optional inTangent, outTangent (0 when missing) and interpolation (smooth when missing; other values are written only when used). Curves run from time 0 (birth) to 1 (death). Gradient colors include alpha as #AARRGGBB, so the campfire's first stop #00FFE8A8 is fully transparent.

Custom modules​

Plugins register modules with services.AddParticleModule<T>("type-name"). Presets save each as its type name and its public fields:

"customModules": [
{ "type": "my.wind", "data": { "strength": 40 } }
]

Modules whose type is not registered, for example because their plugin is switched off, load as unknown modules and are written back unchanged.

Presets in scenes​

A ParticleEmitter component stores either a preset reference or inline settings of the same shape as settings above:

{
"type": "ParticleEmitter",
"data": {
"preset": "0bc97c948d6e484b9513f621244aeccd"
}
}

While preset holds a guid, the preset's settings are played and the inline settings are ignored.