Collideable Particles Module [Self Collisions Update V3.2]

Wassup. Engines other than Roblox have Particles that can actually interact with the world. Roblox is really limited in what particles have to offer. So I decided to fix this issue.
I present to you…
Collideable Particles Module :smiley:
But why?
Here are some Examples.
Have you ever wanted to have a Realistic shower in roblox? Now you can:


Or maybe you wanted Cool sparks that collide with player:

Or Maybe you wanted Particles that can collide with each other:

(You can also make snow with Wind Physics! :exploding_head:)

Well, with this module, it is now possible.
Here is the module: Collision Particles Module
Here is file: CollisionParticlesModuleV3.3.rbxm (10.0 KB)

Here is the place where you can test it out or edit it: PLACE

More Showcases



Tutorial

Module itself is cool and you can make soo many things with it, but because i am dumb, it is hard to use.
That’s why i am making a Tutorial.
Step 1: Make a LocalScript that is inside Actor (It MUST be in a Actor).
Step 2: Edit the script (Of Course). As first, you need to require() the Module. So we write something like this:

local EmmiterCreator = require([Replace This With Place Where You Put Module].ParticleEmmiter)

So if you put your Module in ReplicatedStorage, it should look something like this:
local EmmiterCreator = require(game.ReplicatedStorage.ParticleEmmiter)
Step 3: We make a New Emitter using:

local EmmiterCreator = require([Replace This With Place Where You Put Module].ParticleEmmiter)
local YourEmitter = EmmiterCreator.new()

Step 4: We change some Properties! So there are 3 Most Important Properties: EmmiterObject, Folder and Part. You must set: EmmiterObject to object that will spawn particles, Folder to object that all particles will be parented to, Part to Object that will be spawned.
So we do something like this:

local EmmiterCreator = require([Replace This With Place Where You Put Module].ParticleEmmiter)
local YourEmitter = EmmiterCreator.new()

YourEmitter.Part = [Change This To Your Part]
YourEmitter.EmmiterObject = [Change This To Your Emitter]
YourEmitter.Folder = [Change This To Your Folder]

Step 5: Now you need to set other Properties. You can see what other properties do in other section of this Post.
Step 6: Now we just need to Enable our Particle Emitter. we do this Using YourEmitter.Enabled = true.
Finished Code should look something like this:

local EmmiterCreator = require([Replace This With Place Where You Put Module].ParticleEmmiter)
local YourEmitter = EmmiterCreator.new()

YourEmitter.Part = [Change This To Your Part]
YourEmitter.EmmiterObject = [Change This To Your Emitter]
YourEmitter.Folder = [Change This To Your Folder]

YourEmitter.Enabled = true

Congrats! You made it! If it doesn’t work, just reply to this post about your problem, i will try to help.
You can also check PLACE that i made, edit it, and try understanding the code from it.

Properties

EmmiterObject • BasePart
Object that will Emit Particles

Folder • Instance
Folder where particles will be Parented to when created.

CachceFolder • Instance [DEPRECATED in Version 2.1]
If you want to prevent high memory usage for better FPS you can specify a Folder where parts will be Parented to instead of being deleted. Must Be Different than Folder. Must be original to this Particle Emitter.

MinimumCachce
Makes it so that amount of cachced particles cannot be smaller than this number. Useful when creating explosions using Emit Function.

Enabled • Boolean
Determines whenever Emitter is Emitting Particles on it’s own.

CollisionComplexity • Boolean
When it is on, Collisions will use Sphere, when it’s off, Collisions will use Box. Low Performance Impact.

SelfCollisions • Boolean
Determines if Particles can collide with each other. It is a new feature and it can be glitchy.

SelfSize • Number
Determines Size of Collisions Between Particles.

Iterations • Integer
Determines how many times Collisions Between Particles are calculated. The higher the number, the less glitchier it is.

Mass • Number
It determines the mass of the particles for Collisions Between Particles. Only works for ‘Realistic’ Collision Type.

FluidForce • Number
Determines the force of fluid Particles. Only works for ‘Fluid’ Collision Type.

SelfCollType • SelfCollType (Custom Enum)
It changes the collisions handling between particles when SelfCollisions is turned on. Enums are accessible in Module.

SimulateTurbulence
A new property that fakes Wind Turbulence by objects. By wind turbulence i mean Objects moving wind which affects Particles.

ColliderSize • Number
Size of the collider.

Part • BasePart
Object that the emmiter will emmit.

Friction • Number
Self Explanatory…

Bounce • Number
How strongly Particles Bounce. If 1, it bounces with the same velocity. If 0, it doesn’t bounce at all. If 0.5, it decreases velocity by half when bouncing.

Speed • NumberRange
Determines starting speed of Particles when they are created.

InheritSpeed • Number
Determines how much Emitter Velocity affects Particles Velocity.

Spread • Vector2
The spread of Particles. If 0 they will all go in one direction.

Rate • Number
How many Particles are created per second.

LifeTime • NumberRange
How long Particles will last.

Drag • Number
How much air slows down the particles.

Acceleration • Vector3
Force applied on Particles. Can be used to create Gravity.

Wind • Boolean
If true, Particles will be affected by wind.

WindSpeed • Number
How fast wind changes position.

WindScale • Number
It is hard to explain. Basically wind is made by perlin noise. So it changes how Frequently there are changes in Noise based on Particle position.

WindStrenght • Number
How strong wind is.

WindDirection • Number
Direction of wind.

DistanceFPS • Number
Makes Particles that are far away from camera update less often. So if you set it to 24, then the distance from camera is 28, then it will update by half FPs, and if distance was 72, it would update by quarter FPS

EveryFrame • Function
This is a function that can be used to change particle properties every frame. Here is an example on how you can use it:

--changes EveryFrame property of Emitter to function that will change particle size based on Velocity
function Emitter:EveryFrame(Pos : Vector3, Velocity : Vector3, LifeTime : number)
	return {Size = Vector3.new(0.2, 0.2, Velocity.Magnitude / 50)}
end

--This is a Really Bad Way of changing EveryFrame Property. Please use the one above
Emitter.EveryFrame = function(Pos : Vector3, Vel : Vector3, LifeTime : number)
	return {Size = Vector3.new(0.2, 0.2, Vel.Magnitude / 50)}
end

--You can also change other properties of Particle. For example this code changes Color based on Velocity
function Emitter:EveryFrame(Pos : Vector3, Vel : Vector3, LifeTime : number)
	return {Color = Color3.new(0, 0, 1):Lerp(Color3.new(1, 0, 0), math.clamp(Vel.Magnitude / 40, 0, 1)}
end

--You can also change multiple values. This code changes Size and Color based on Velocity.
function Emitter:EveryFrame(Pos : Vector3, Vel : Vector3, LifeTime : number)
	return {Size = Vector3.new(0.2, 0.2, Velocity.Magnitude / 50), Color = Color3.new(0, 0, 1):Lerp(Color3.new(1, 0, 0), math.clamp(Vel.Magnitude / 40, 0, 1)}
end

OnCollision • Function
This function can be used to change Particles Properties. It works like EveryFrame function but happens only on collision so it has better performance.

OnSpawn • Function
This function can be used to change Particles Properties. It works like EveryFrame function but happens only when particle is created.

BeforePhysics • Function
This function runs before Physics Calculations. Can be used to AddForces.

CameraCulling • Boolean
–Toggles whenever particles should use camera culling. Makes it so that particles behind camera don’t change position. Better Performance if you have really big emitters.

Functions

AddForce(Force : ForceTypeEnum)
It is used to add Forces on Particles. Forces don’t stay forever, you need to add them every frame.
There are currently 3 ForceTypes you can use:

  • Repel: Repels all Particles in Range. (Can be used to make Explosions or Planet Gravity and more)
  • RepelConstant: Repels all particles in Range but Force isn’t affected by Distance.
  • Turbulence: Adds Turbulence Force. (Can be used in pair with WindPhysics to make it look more realistic)
    Here is a tutorial how to use it:
--First we make a Emitter
local EmmiterModule = require([Replace This With Place Where You Put Module].ParticleEmmiter)
local YourEmitter = EmmiterCreator.new()

--Next we change some properties (in this case i only change the important ones)
YourEmitter.Part = [Change This To Your Part]
YourEmitter.EmmiterObject = [Change This To Your Emitter]
YourEmitter.Folder = [Change This To Your Folder]

-- We change BeforePhysics Function. We will use it to add Force Every Frame
function YourEmitter:BeforePhysics()
	--We get the Player's Character
	local Char = game.Players.LocalPlayer.Character
	--Then we check if it exists
	if Char then
		--We get Player's Root
		local HRP : Part = Char:FindFirstChild("HumanoidRootPart")
		--And we also check if it exists
		if HRP then
			--Now we make a new Force that Attracts Particles to player
			local MyForce = EmmiterCreator:NewForce(EmmiterCreator.TypeForce.Repel)
			--Notice how we change the power of the Force to a negative number. This makes it so that particles are Attracted, not Repeled
			MyForce.Power = -3
			MyForce.Range = 10
			MyForce.Position = HRP.Position
			Emitter:AddForce(MyForce)
		end
	end
end

YourEmitter.Enabled = true

Emit(Amount)
It emits an Amount of Particles. Can be used to create explosions.

UpdateLog

Release
The Release of this module

Version 1.1
-Added Better Particles Spread (Now it works like default Roblox ParticleEmitter Spread).
-Added new Property DistanceFPS. Check Properties Section for info.

Version 1.2
-Changed Friction and Drag Code to work with every FPS.

Version 2
-2x better FPS! It was possible by merging 2 modules into 1 and using BulkMoveTo().

Version 2.1
-Added new and faster Cachce Code. CachceFolder is now Deprecated.

Version 2.2
-Added new property called EveryFrame. It can be used to change Particles properties every frame. You can find more info about it in Properties Section.

Version 2.3
-Added new property called CameraCulling.

Version 2.4
-Added new property called InheritSpeed.
-Improved Velocity calculation with moving objects. Now Spinning Parts Affect Velocity Too.

Version 2.5
-Changed Property type of Speed and LifeTime from Number to NumberRange. It will be easier now to spawn particles with randomized Speed and LifeTime.
-Added new Property called MinimumCachce. It makes it so that number of cachced particles cannot be smaller than this value. Useful for creating Explosions without lag.

Version 3
-Changed Collision Code to be more accurate. Now particles don’t get stuck in players.
-Added new Function AddForce. It can be used to add Forces like Repel or Turbulence.
-Added new Property called BeforePhysics.

Version 3.1
-New Three Experimental Properties: SelfCollisions, SelfSize, Iterations. It makes it possible to simulate particles that collide with eachother.
-New Property SimulateTurbulence. It tries to fake Objects affecting wind which affects Particles.

Version 3.2
-New Three Properties: FluidForce, Mass, SelfCollType. They are used to better customize Collisions between Particles.
-Better Collisions Code.

!!!Remember!!! This module shouldn’t replace roblox default Particle Emitters because of the performance. It should only be used to create cool effects.

That’s all! If you have any ideas or questions, you can reply to this topic.

Edit: I forgot to mention. Sadly, you cannot simulate Rectangles because for now it is impossible to get surface direction using collisions. Currently, surface normal is detected using raycast so it could be glitchy. I will probably add this feature when roblox will allow BlockCast to be called in Parallel.

How Would You Rate this Module?

  • 5 Stars
  • 4 Stars
  • 3 Stars
  • 2 Stars
  • 1 Stars

0 voters

Also, if you need help implementing it to your game, i can help you by going on Team Create or i can just Tell you how to do it. I know it might be hard because the Tutorial is very bad.

159 Likes

I was Able to Make Snow Using this module:

22 Likes

Very cool! It would be neat if particles that are below a certain speed or are far away from the camera update less often to save performance

7 Likes

Looks cool! I think the test place is set to private.

Roblox VFX have now advanced thanks to this module!

3 Likes

This looks amazing! Great job!

3 Likes

Oh, im stoopid. Now i fixed it. You should be able to test it now.

This is a really good idea. I will try to implement this feature in next update.

Looks awesome! I’ll definitely try something out with this, really gives great vfx ideas

Update
-Changed Spread Property to act like Roblox Default ParticleEmmiter Property.
-Added New Property Based on @baseparts’s idea called DistanceFPS. It makes so that Particles over this distance will update with lower FPS. The further the camera is, the Lower the FPS.

4 Likes

Update
-Changed Friction and Drag Code to work with every FPS

With DistanceFPS Optimization i was able to simulate 3780 Particles :exploding_head: :scream:

9 Likes

Update 2
Ok, this update can blow you mind. :exploding_head:
Before the update, when simulating 6300 Particles and setting DistanceFPS to 20 i had somewhere around ~30 FPS.
After this update, when simulating the same amount of Particles with the same DistanceFPS i was getting 60FPS! :exploding_head: :exploding_head: :exploding_head:
Of course, if i would set DistanceFPS to something higher, i would not have 60 FPS, but still this is impressive.
To get this amount of FPS i merged 2 Modules into 1 and used something called BulkMoveto()

I cannot wait until someone will post their creation with this module!

14 Likes

That’s a huge improvement, I’m definitely going to use this inside of my game. Congrats on an amazing module!

Here's some more stuff I think could save performance
  • This won’t save performance by much but I notice you make new params every heartbeat. Since your FilterDescendantsInstances are folders you could make the params outside of heartbeat and reuse them.

  • I notice you reparent dead particles to the Cache folder, I suggest just leaving all particles inside the same folder since you’re already moving dead particles to a far away cframe. Instead you could insert your dead particles inside a cache table which can be use later.

9 Likes

Can you provide an RBXM file instead of the module link or alongside it? it’s way more convenient

4 Likes

First of all. The average rbxm file size is 800 kb (i’m being generous), You would need 1,497 rbxm files to fill 1 GB and 179,657 rbxm files to fill 120 GB

Second of all. It’s not a bad idea and would be even very useful if you are organized or use external editors. For example, Let’s say you are developing your game and you need a particle collision system for your game ystem so you decide to install this, But oh noo it’s a roblox model so now you have to install it, close your game, reopen it, insert the model, sync it with your editor to be able to use it

Third of all. It’s really a personal preference

1 Like

Ok, i will do that when i will have free time.

Update 2.1
-Replaced Cachce Code with a better one. Now you should see a 8 FPS difference.
-CachceFolder Property is now Deprecated

Now I can make better particles (don’t worry I won’t replace it with the default particle emitter from roblox)

1 Like

!!!WARNING!!!
In Version 2.1 there was a bug in code that could Massivelly destroy your FPS. If you downloaded Version 2.1 before this message, please reinstall it!