How to prevent rain from traveling through parts without taking up too much memory?

Hey guys,

i was trying to make a rain script that wouldn’t travel through parts (Ex. a roof, so a house wouldn’t just have rain in it.)

i tried using raycasting but i feel like i’m doing it incorrectly.

i would spawn an attachment within the part that emits the rain particles and raycast to set the lifetime of the particle to dynamicly end when it “Hits” something.
in reality i’m just calculating it through speed and distance.

however, i feel like spawning an extreme amount of attachments would not be ideal.

for obvious reasons.

is there a way to detect when a particle has been emitted, then fire a ray to that position? or possibly emit the particle from the position that the ray fired from?

make the rain local, and a raycast that starts from the head of the player and goes up until it touches a part, if it does, disable the rain

Set your particle emitter and have this script:

local RunService = game:GetService("RunService")

-- Settings
local rainEmitter = -- reference to your particle emitter
local raycastInterval = 0.1 -- How often to perform raycasts
local rainHeight = 50 -- Height from which to cast rays

-- Function to update the rain particles
local function updateRain()
    local emitterPosition = rainEmitter.Parent.Position
    local rayOrigin = emitterPosition + Vector3.new(0, rainHeight, 0)
    local rayDirection = Vector3.new(0, -rainHeight * 2, 0) -- casting downwards

    local params = RaycastParams.new()
    params.FilterType = Enum.RaycastFilterType.Blacklist
    params.FilterDescendantsInstances = {rainEmitter.Parent} -- Ignore the part with the emitter

    -- Cast the ray
    local result = workspace:Raycast(rayOrigin, rayDirection, params)

    if result then
        local hitPosition = result.Position
        local distance = (rayOrigin - hitPosition).Magnitude

        -- Adjust particle lifetime based on distance
        local particleSpeed = rainEmitter.Speed
        local particleLifetime = distance / particleSpeed

        rainEmitter.Lifetime = NumberRange.new(particleLifetime)

        -- (Optional) Adjust particle transparency based on hit material
        if result.Instance.Material == Enum.Material.Glass then
            rainEmitter.Transparency = NumberSequence.new(0.5)
        else
            rainEmitter.Transparency = NumberSequence.new(0)
        end
    else
        rainEmitter.Lifetime = NumberRange.new(0) -- No lifetime if no hit
    end
end

-- Run the update function at regular intervals
RunService.Heartbeat:Connect(function()
    updateRain()
end)

while this is an interesting idea, it would set the ENTIRITY of the rainparticles to the highest point. (by looking at the code, i believe this is what would happen.) this means that the rain would have its lifetime be set to intersect with the highest point on the map. meaning, all of the rain would be above the ground. also, it only raycasts at the center of the part.

also, i tried it in-game and i didnt actually change the lifetime correctly. it would go WAAYYY past the part.

this is a very interesting idea, however, as soon as you walked under somthing, it would stop raining “outside”. that would be pretty janky, although the idea sounds very cool.