ParticleEmitterComponent Class
Definition
Namespace: Brine2D.Systems.Rendering
Component for particle emission and rendering.
Inheritance System.Object → Component → ParticleEmitterComponent
| Properties | |
|---|---|
| BirthSubEmitters | Optional list of sub-emitter configs triggered when a particle from this emitter \<b>spawns\</b>. For each config a burst of sub-particles is spawned at the new particle's world position. Useful for spawn-impact effects such as a smoke puff or splash that appears at the point of materialisation. Sub-particles are managed internally by ParticleSystem and do not require additional ECS entities or components. Sub-particles do not chain — sub-emitters on sub-emitters are not supported. This list is not captured by CaptureDefaultState() because configs are typically set once at design time and are not expected to change between resets. |
| BoxAngle | Rotation angle in \<b>radians\</b> applied to the Box spawn area. Rotates the box around its centre so spawn offsets follow the box orientation. 0 \(default\) = axis-aligned. |
| BurstCount | Number of particles to emit in a single burst. Only used when IsBurst is true. |
| CleanupForPool | Registered by ParticleSystem the first time this emitter is encountered. Invoked by Brine2D.Systems.Rendering.ParticleEmitterComponent.OnRemoved to return all live particles to the pool before the component is detached, preventing a pool leak when the entity is destroyed. |
| ColorGradient | Optional multi-stop color gradient sampled over a particle's lifetime \(t = 0\.\.1\). When set, takes priority over Brine2D.Systems.Rendering.ParticleEmitterComponent.StartColor and Brine2D.Systems.Rendering.ParticleEmitterComponent.EndColor. Stops are evenly distributed; supply at least two entries. Note: per-particle StartColorVariation / EndColorVariation are not applied when a gradient is active. |
| ConeAngle | Full cone spread angle in \<b>degrees\</b> for Cone emitters. Each particle's direction is randomised within ±ConeAngle/2 of Brine2D.Systems.Rendering.ParticleEmitterComponent.InitialVelocity. |
| Damping | Exponential drag coefficient applied each second via velocity *= exp(-Damping * dt). Frame-rate independent; a value of ~0.693 halves speed each second. 0 \(default\) means no drag. Gravity is applied after damping. Note: when StartSpeedMultiplier / EndSpeedMultiplier are active they control the magnitude of the base velocity component independently; combining both features is supported but the multiplier curve takes priority over damping for the non-gravity component. |
| DeathSubEmitters | Optional list of sub-emitter configs that are triggered when a particle from this emitter expires naturally. For each config a burst of sub-particles is spawned at the dying particle's world position. The sub-particles are managed internally by ParticleSystem and do not require additional ECS entities or components. Sub-particles do not chain — sub-emitters on sub-emitters are not supported. This list is not captured by CaptureDefaultState() because configs are typically set once at design time and are not expected to change between resets. |
| Delay | Delay in seconds before emission begins after the emitter is first activated or restarted after Stop(). 0 \(default\) means emit immediately. The delay is re-applied on each loop iteration when Loop is true. |
| DelayTimer | Elapsed time in seconds counting toward Delay. When this reaches Delay the emitter begins emitting normally. Reset by Stop() and ResetToDefaultState(). |
| Duration | Optional duration in seconds for continuous emitters. When set, the emitter automatically stops emitting after this many seconds have elapsed. Does not affect burst emitters. Set to null \(default\) for an infinitely running emitter. |
| EndColorVariation | Per-particle additive randomisation applied to each channel of Brine2D.Systems.Rendering.ParticleEmitterComponent.EndColor independently. Each channel is nudged by a random value in [-V, +V] where V is the corresponding channel of this color, then clamped to [0, 255]. |
| EndSizeVariation | Per-particle randomisation of Brine2D.Systems.Rendering.ParticleEmitterComponent.EndSize. The end size is nudged by a random value in [-EndSizeVariation, +EndSizeVariation], clamped to >= 0. |
| EndSpeedMultiplier | Multiplier applied to the spawn-speed of each particle at t = 1 \(death\). Default 1 \(no change\). Set to 0 to decelerate particles to a halt over their lifetime. |
| Forces | Optional list of extra forces \(attractors, wind zones, etc\.\) applied to every live particle during the update pass. Forces are evaluated in order and their results are summed into BaseVelocity, making them subject to subsequent damping and speed-over-lifetime scaling. This list is not captured by CaptureDefaultState() because force objects are typically configured once and shared across resets. |
| InitialRotationVariation | Absolute random range in \<b>radians\</b> added to Brine2D.Systems.Rendering.ParticleEmitterComponent.InitialRotation at spawn. Each particle gets a value in [-InitialRotationVariation, +InitialRotationVariation]. Use MathF.PI for a fully randomised initial rotation across the whole circle. |
| IsBurst | When true, emits BurstCount particles in a single frame then stops. The emitter disables itself automatically once all burst particles have expired, unless Loop is also true, in which case it re-arms and fires again. |
| IsPaused | When true, all particle aging, movement, and new emission are frozen. Call Resume() to continue. |
| LifetimeFractionSubEmitters | Optional list of lifetime-fraction triggers. Each entry fires a sub-emitter burst once per particle when the particle's age crosses the specified normalised lifetime fraction \(0 = birth, 1 = death\). Useful for mid-flight effects such as a rocket igniting a secondary thruster at half its life. Fractions are evaluated every update frame; if a large delta-time steps past a threshold in a single frame the trigger still fires exactly once for that particle. Sub-particles do not chain — sub-emitters on sub-emitters are not supported. This list is not captured by CaptureDefaultState(). |
| LineAngle | Rotation angle in \<b>radians\</b> for the Line shape. 0 = horizontal, MathF.PI / 2 = vertical. |
| LineLength | Length of the Line spawn segment in world units. When set to a positive value, takes priority over Brine2D.Systems.Rendering.ParticleEmitterComponent.ShapeSize.X for line emitters, giving a more readable API. Leave at 0 \(default\) to use Brine2D.Systems.Rendering.ParticleEmitterComponent.ShapeSize.X. |
| Loop | When true and Duration is set, the emitter automatically restarts its emission cycle once all particles from the previous cycle have expired. The delay is re-applied on each loop iteration. OnEmitterFinished does not fire while looping. Also works with burst emitters \([IsBurst](IsBurst.md 'Brine2D\.Systems\.Rendering\.ParticleEmitterComponent\.IsBurst') = true\): the burst re-arms and fires again after all particles from the previous burst have expired. |
| OnEmitterFinished | Optional callback invoked once by ParticleSystem when the emitter finishes: either when a burst emitter's last particle expires \(and [Loop](Loop.md 'Brine2D\.Systems\.Rendering\.ParticleEmitterComponent\.Loop') is false\), or when a Duration-limited continuous emitter's last particle expires after emission has stopped \(and [Loop](Loop.md 'Brine2D\.Systems\.Rendering\.ParticleEmitterComponent\.Loop') is false\). Not invoked by Stop() or ResetToDefaultState(). |
| OnParticleDied | Optional callback invoked by ParticleSystem when a particle expires naturally. The particle is passed with its final state and is returned to the pool immediately after the callback returns. Do not hold a reference to the particle. Not invoked when Stop() force-clears particles. This property is not captured by CaptureDefaultState(). |
| OnParticleSpawned | Optional callback invoked by ParticleSystem immediately after a particle is spawned and added to the active list. Do not hold a reference to the particle beyond the callback. This property is not captured by CaptureDefaultState(). |
| ParticleFrames | An ordered array of atlas regions used as animation frames over the particle's lifetime. When set, takes priority over Brine2D.Systems.Rendering.ParticleEmitterComponent.ParticleAtlasRegion. Frames are distributed evenly across the lifetime \(frame 0 at birth, last frame at death\). |
| RenderLayer | Draw order for this emitter relative to other emitters processed by the same ParticleSystem. Lower values are rendered first \(further back\). Emitters with the same layer are rendered in entity-creation order. |
| RotationSpeed | Rotation speed in \<b>radians per second\</b>. |
| RotationSpeedVariation | Absolute random range \(\<b\>radians/sec\</b\>\) added to RotationSpeed at spawn. Each particle gets a value in [-RotationSpeedVariation, +RotationSpeedVariation]. This is an additive range, so it works even when RotationSpeed is zero. |
| SimulateInLocalSpace | When true, particles are simulated in local space relative to the emitter entity. Moving the entity moves all live particles with it. Useful for exhaust trails, auras, and effects that should remain attached to a moving object. When false \(default\), particles are simulated in world space and drift freely after spawn. Velocity direction: when local-space simulation is active, Brine2D.Systems.Rendering.ParticleEmitterComponent.InitialVelocity is treated as a local-space direction — it is not rotated by Rotation at spawn time. This means particles always travel in a fixed direction relative to the entity's local axes. If you need velocity to follow the entity's world rotation instead, set SimulateInLocalSpace to false and use VelocityInheritance to carry the entity's momentum. Note: if the entity's Scale changes after particles have already spawned, all live particle positions will appear to stretch or compress relative to the entity origin, because positions are multiplied by localScale each render frame. Avoid animating scale on entities that use local-space particle simulation with live particles. |
| SizeVariation | Per-particle randomisation of Brine2D.Systems.Rendering.ParticleEmitterComponent.StartSize. The spawned size is nudged by a random value in [-SizeVariation, +SizeVariation], clamped to >= 0. |
| SpawnOnPerimeter | When true, particles for Circle and Cone spawn exactly on the perimeter of the circle \(radius = [Brine2D\.Systems\.Rendering\.ParticleEmitterComponent\.SpawnRadius](https://learn.microsoft.com/en-us/dotnet/api/brine2d.systems.rendering.particleemittercomponent.spawnradius 'Brine2D\.Systems\.Rendering\.ParticleEmitterComponent\.SpawnRadius')\) rather than uniformly distributed within it. Useful for ring bursts and shockwave effects. |
| StartColorVariation | Per-particle additive randomisation applied to each channel of Brine2D.Systems.Rendering.ParticleEmitterComponent.StartColor independently. Each channel is nudged by a random value in [-V, +V] where V is the corresponding channel of this color, then clamped to [0, 255]. |
| StartSpeedMultiplier | Multiplier applied to the spawn-speed of each particle at t = 0 \(birth\). Linearly interpolated toward EndSpeedMultiplier over the particle's lifetime. Default 1 \(no change\). When either multiplier differs from 1, speed-over-lifetime is active and takes priority over Damping for the non-gravity component of velocity. |
| StopRequested | When true, the next ParticleSystem update will return all live particles to the pool and clear the list. Set by Stop() and ResetToDefaultState(). |
| TrailHeadAlpha | Alpha of the trail segment nearest to the particle head \(t = 1, newest position\). Defaults to 0.8 so the head end of the trail is nearly opaque. |
| TrailHeadSizeRatio | Size multiplier for the trail segment nearest to the particle head \(t = 1, newest position\). Defaults to 1.0 so the head-side segment matches the particle's current size. |
| TrailMode | Controls how the trail history is rendered. Defaults to Sprites. Use Lines for a continuous ribbon on untextured particles. |
| TrailTailAlpha | Alpha of the trail segment farthest from the particle head \(t = 0, oldest position\). Defaults to 0.0 so the tail fades to transparent. |
| TrailTailSizeRatio | Size multiplier for the trail segment farthest from the particle head \(t = 0, oldest position\). Defaults to 0.5 so the tail is half the particle's current size. |
| TurbulenceFrequency | Spatial frequency of the turbulence noise field. Higher values produce tighter, higher-frequency swirls. Default is 0.02 \(world\-unit scale\). |
| TurbulenceStrength | Strength of per-particle velocity noise applied every frame using coherent value noise sampled from particle position and elapsed time, scaled so the effect is frame-rate independent. 0 \(default\) disables turbulence. Turbulence is additive — it does not replace the base velocity or interact with Damping or StartSpeedMultiplier/EndSpeedMultiplier. |
| VelocityInheritance | Fraction of the emitter entity's instantaneous velocity \(units/second\) added to each newly-spawned particle's velocity at birth. 0 \(default\) means no inheritance. 1 means full inheritance. Only applied when the emitter has a TransformComponent. When SimulateInLocalSpace is true the inherited velocity is still computed from the entity's world-space motion so particles correctly carry the entity's momentum. |
| VelocitySpread | Random angular spread in \<b>degrees\</b> applied to Brine2D.Systems.Rendering.ParticleEmitterComponent.InitialVelocity at spawn. Each particle's direction is nudged by a random value in [-VelocitySpread/2, +VelocitySpread/2] degrees. Note: when Brine2D.Systems.Rendering.ParticleEmitterComponent.Shape is Cone, ConeAngle is used instead and this property has no effect. |
| WarmupDuration | Pre-simulation duration in seconds applied on the first ParticleSystem update after the emitter becomes active. Use this to make looping ambient effects appear already running when they first appear on screen. 0 \(default\) disables warmup. |
| Methods | |
|---|---|
| CaptureDefaultState() | Captures the current configuration as the default state that ResetToDefaultState() will restore. Call this once you have finished configuring the emitter. IsPaused is intentionally excluded — reset always resumes the emitter. ColorGradient and ParticleFrames arrays are deep-copied so subsequent in-place mutations of those arrays do not silently corrupt the captured state. Reassigning the property to a new array is always safe regardless. |
| Pause() | Freezes all particle aging, movement, and new emission. |
| Play() | Starts or restarts the emitter from a clean state. Re-enables the emitter, begins emission, resumes if paused, re-arms the burst, and resets all timers. Any pending Stop() is cancelled so live particles are not cleared. |
| ResetBurst() | Re-arms the burst so it fires again on the next update. Has no effect on continuous emitters. |
| ResetToDefaultState() | Restores the configuration that was captured by the last call to CaptureDefaultState(). Throws if CaptureDefaultState() has never been called. Live particles are scheduled for pool return on the next system update. IsPaused is always reset to false. |
| Resume() | Resumes a previously paused emitter. |
| Stop() | Stops emission and schedules all live particles to be returned to the pool on the next ParticleSystem update. Brine2D.Systems.Rendering.ParticleEmitterComponent.ParticleCount reaches zero after that update. Also resumes the emitter if it was paused. |
| TryResetToDefaultState() | Attempts to restore the default state if it has been captured, otherwise does nothing. Prefer ResetToDefaultState() when you expect a captured state to always exist. |