2D Particle Emitter

This module aims to mimic the existing Roblox ParticleEmitter object to make it easier to create 2d particles and port over existing particle emitters (with a few tweaks of course!)

Short video of this module in action, along with a comparison:


Notable changes that you have to account for when making your own particle emitter:

  • Speed determines how much the particle progresses in pixels (offset) per second.
  • Size is in offset.

You can get and view the source code via Github or the Roblox Creator Store.
A quick usage example can be found within the Github provided above.

44 Likes

Here is another demonstration of what this module is capable of.
Made these today for my game which took a few hours to do.

RobloxStudioBeta_F26Pe9MwQw

8 Likes

2D Particle Emitter v0.0.3

  • Replaced math.random with the Random class internally
  • Added .fromParticle constructor function which lets you create a 2d particle object using an existing particle emitter as a base

Example usage:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ParticleEmitter = require(ReplicatedStorage:WaitForChild("ParticleEmitter"))

-- Size & Speed are being set here because they work very differently
-- from regular ParticleEmitters

local sparklesEmitter = ParticleEmitter.fromParticle(script.ParticleEmitter)
sparklesEmitter.Size = NumberSequence.new({
	NumberSequenceKeypoint.new(0, 3.75),
	NumberSequenceKeypoint.new(0.175, 15),
	NumberSequenceKeypoint.new(1, 0),
})

sparklesEmitter.Speed = 15
sparklesEmitter.Parent = script.Parent
3 Likes

Will i have to spend a few hours to set this up too

we ALL will be using TS module (good module, imma use it for my game

6 Likes

Nope, it only took a few hours because I had to come up with ideas for these particles
Refer to the example given above or within the Github to get started

2 Likes

The rainbow text on the bottom isn’t a particle effect or am I mistaken?

It’s not. It just happened to be included in the gif

Very interesting. I will check it out.
Mind adding these demonstrations to the github?

Sorry these demonstrations were made specifically for my game so I can’t make them public. However I can make some example particles next week since I’m on vacation right now.

Pretty straight forward to use. Thanks for the contribution!

-- Script 1
local ParticleEmitterModule = require(ReplicatedStorage.Modules:WaitForChild("2DParticleEmitter"))

local Visuals = {}

function Visuals.CreateHealthGainEmitter(parent)
	local emitter = ParticleEmitterModule.new()
	emitter.Parent = parent
	emitter.Texture = "rbxassetid://80066527587562"
	emitter.Color = ColorSequence.new(Color3.fromRGB(50, 255, 50))
	emitter.Size = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 28),
		NumberSequenceKeypoint.new(0.5, 36),
		NumberSequenceKeypoint.new(1, 18),
	})
	emitter.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 0),
		NumberSequenceKeypoint.new(0.7, 0.2),
		NumberSequenceKeypoint.new(1, 1),
	})
	emitter.ZOffset = 5
	emitter.EmissionDirection = "Top"
	emitter.Lifetime = NumberRange.new(0.8, 1.3)
	emitter.Speed = NumberRange.new(30, 50)
	emitter.SpreadAngle = 25
	emitter.RotSpeed = NumberRange.new(-45, 45)
	emitter.Rotation = NumberRange.new(0, 360)
	emitter.Enabled = false
	return emitter
end

return Visuals
--Script 2
local healthGainEmitter = Visuals.CreateHealthGainEmitter(ParticleFrame)
-- this fires when my local player gains more than 1% max hp
healthGainEmitter:Emit(1)
2 Likes

2D Particle Emitter v0.0.4


Additions

  • Added new methods:
    • :BindToRenderStepped()
    • :BindToHeartbeat()
    • :BindToStepped()
    • :Unbind()
    • :Update(deltaTime: number)
  • Added new properties:
    • AspectRatio

Changes

  • Emitters no longer create a new RenderStepped loop. Connections now have to be started manually via the new methods listed above. Alternatively, you can ditch the bind methods entirely and just update the emitter yourself if needed.
  • Added support for the Acceleration property.
  • Added NumberRange to ZOffset type.
  • Added AspectRatio property. This allows you to apply an aspect ratio to particles.

Example usage:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ParticleEmitter = require(ReplicatedStorage:WaitForChild("ParticleEmitter"))

-- Short PSA for using the Acceleration property
-- X: (+) = Right, (-) = Left
-- Y: (+) = Down, (-) = Up
-- the direction is weird because it's relative to your screen

local sparklesEmitter = ParticleEmitter.fromParticle(script.ParticleEmitter)
sparklesEmitter.AspectRatio = 1 / 2
sparklesEmitter.Acceleration = Vector2.new(40, 40) -- Bottom Right
sparklesEmitter.Parent = script.Parent

sparklesEmitter:BindToRenderStepped() -- bind emitter to RenderStepped
sparklesEmitter:Unbind() -- unbinds current connection

while true do
    local deltaTime = task.wait(1)
    sparklesEmitter:Update(deltaTime) -- update it yourself if you want to
end

You can get and view the source code via Github or the Roblox Creator Store.
A quick usage example can be found within the Github provided above.

1 Like

I don’t think that you pushed the correct version of this module to github, I cant seem to find the new additions

The new additions are in the GitHub but it appears that I forgot to add them to the Types module so they haven’t been showing up properly :grimacing:

Will fix this soon.

2 Likes

This was so promising, have you abandoned this project?

add a third dimension please

I still actively use this module to this day for my UI, but I just haven’t had a reason to add any other features at the moment. I’m willing to look through pull requests on the github repository if anyone is interested in contributing.

1 Like

Oh, I meant it since I still didnt see the new methods in the latest github version.

2D Particle Emitter v0.0.5


Additions

  • Added Bind(loop: Types.Loops) method to bind the particle emitter to a RunService loop
    • BindToRenderStepped(), BindToStepped(), and BindToHeartbeat() uses this internally now
  • Added Drag property — applies exponential speed decay to particles over their lifetime
    • Carried over from the Roblox ParticleEmitter Drag property
  • Added Constructor.clone() for cloning an existing 2D particle emitter
  • Rewrote particle movement to update positioning incrementally instead of lerping to a fixed endpoint

Bug Fixes

  • Fixed Destroy() throwing an error when the emitter was never bound to a loop
  • _connection property is now properly being set to nil after unbinding

Changes

  • Added missing methods to ParticleEmitter type:
    • Bind
    • Unbind
    • Update
    • BindToRenderStepped
    • BindToHeartbeat
    • BindToStepped
  • Added missing fields to Particle type:
    • TimeScale
    • AspectRatio
    • _currentAcceleration
    • _elapsed
  • Removed _random from ParticleEmitter
    • Particles now internally use a RANDOM constant
  • TimeScale property is now functional

Example usage:

local ParticleEmitter = require(...)
local emitter = ParticleEmitter.new()

emitter.Color = Color3.new(1, 1, 1)
emitter.Size = 32
emitter.Texture = "rbxasset://textures/particles/sparkles_main.dds"
emitter.Transparency = 0
emitter.ZOffset = 1
emitter.EmissionDirection = "Top"
emitter.Enabled = true
emitter.Lifetime = NumberRange.new(5, 10)
emitter.Rate = 20
emitter.Rotation = 0
emitter.RotSpeed = 0
emitter.Speed = 25
emitter.SpreadAngle = 0
emitter.Acceleration = Vector2.new(0, 40)
emitter.Drag = 0.5
emitter.AspectRatio = 1
emitter.TimeScale = 1

emitter.Parent = script.Parent
emitter:Bind("RenderStepped") -- alternatively, :BindToRenderStepped()
emitter:Emit(25)

The Github has been updated to reflect the new additions and changes made to the module. Updated usages examples can be found in the README.md.

You can get and view the source code via Github or the Roblox Creator Store.