Hey all, so I’ve been working on a rain system that uses raycasting, beams, and particles to create a realistic rain effect.
It seems to work pretty well, but after some time of running it, the system starts to cause lag. I have no idea why this is, but I’ve tried all sorts of methods to minimize the lag, such as changing from beams to parts, but nothing seemed to be working.
local RainRadius = 100
local MaxRainDistance = 800
local RainSpeed = 300
local Rate = 10
local CurrentMaxRainCount = 500 -- Stop the rain from creating more drops than it can destroy. (seems to cause lag once the rain has reached this number)
local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist
local Debris = game:GetService("Debris")
local RS = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Terrain = workspace.Terrain
local PartTemplate = Instance.new("Part")
PartTemplate.Size = Vector3.new(0.2, 0.2, 0.2)
PartTemplate.Transparency = 1
PartTemplate.CanCollide = false
PartTemplate.Anchored = true
PartTemplate.Name = "RainSplashPart"
local RainPartsFolder = Instance.new("Folder")
RainPartsFolder.Name = "RainContent"
RainPartsFolder.Parent = workspace
local AbsorbantMaterials = { -- Materials that don't create the rain splash effect
Enum.Material.Grass,
Enum.Material.Fabric,
Enum.Material.Sand,
}
local DeltaTime = 0
local RainDeltaIncrement = RainSpeed
local BlackListIndex = 0
local Blacklist = {}
local function SetupBlacklist(InstanceToSearch)
for i, child in ipairs(InstanceToSearch:GetChildren()) do
if child:IsA("BasePart") and (not child.CanCollide or child.Transparency == 1) then
BlackListIndex = BlackListIndex + 1
table.insert(Blacklist, BlackListIndex, child) -- Add the part to the blacklist
else
SetupBlacklist(child) -- Continue searching for baseparts
end
end
end
function CastRain()
Params.FilterDescendantsInstances = Blacklist
if #RainPartsFolder:GetChildren() <= CurrentMaxRainCount then -- Stop the rain from creating too many instances (seems to create lag when this statement becomes false)
local RainOrigin = game.Workspace.CurrentCamera.CFrame.Position + Vector3.new(0, math.random(100, 120), 0)
local RandomPosition = RainOrigin + Vector3.new(math.random(-RainRadius/2, RainRadius/2), 0, math.random(-RainRadius/2, RainRadius/2))
local Direction = Vector3.new(0, -MaxRainDistance, 0)
local RainRay = workspace:Raycast(RandomPosition, Direction, Params)
if RainRay then
local HitPos = RainRay.Position
local Dist = (RainOrigin - HitPos).Magnitude
-- Create the rain drop
local RainAttachment1 = Instance.new("Attachment")
RainAttachment1.WorldPosition = RandomPosition + Vector3.new(0, 3, 0)
local RainAttachment2 = Instance.new("Attachment")
RainAttachment2.WorldPosition = RandomPosition - Vector3.new(0, 3, 0)
local RainBeam = script.RainBeam:Clone()
RainBeam.Parent = RainPartsFolder
RainBeam.Attachment0 = RainAttachment1
RainBeam.Attachment1 = RainAttachment2
RainAttachment1.Parent = Terrain
RainAttachment2.Parent = Terrain
-- Move the rain drop until it hits the surface
repeat
RS.RenderStepped:Wait()
RainAttachment1.WorldPosition = RainAttachment1.WorldPosition - Vector3.new(0, RainDeltaIncrement, 0)
RainAttachment2.WorldPosition = RainAttachment1.WorldPosition - Vector3.new(0, RainDeltaIncrement, 0)
until RainAttachment2.WorldPosition.Y <= HitPos.Y
-- Create the splash effect
if not table.find(AbsorbantMaterials, RainRay.Instance.Material) then
local SplashPart = PartTemplate:Clone()
SplashPart.Parent = RainPartsFolder
SplashPart.Position = HitPos
local SplashParticle = script.SplashEffect:Clone()
SplashParticle.Parent = SplashPart
SplashPart.Material = RainRay.Instance.Material
SplashParticle:Emit(1)
Debris:AddItem(SplashPart, SplashParticle.Lifetime.Max)
end
RainBeam:Destroy()
RainAttachment1:Destroy()
RainAttachment2:Destroy()
end
end
end
RS.RenderStepped:Connect(function(step)
for i = 1, Rate do
CastRain()
RainDeltaIncrement = RainSpeed * step
DeltaTime = step
end
end)
SetupBlacklist(workspace)
while true do -- Loop every 2 seconds to check and add new parts that get added to blacklist.
wait(2)
SetupBlacklist(workspace)
end
Some help will be greatly appreciated as always.