Code sample for Explosion.Hit has a memory leak

The code sample provided for Explosion.Hit has a memory leak. The .Hit event never gets cleaned up, resulting in a memory leak. This can be fixed by keeping a reference to the connection, and disconnecting it after a few seconds.

Affected Page: Explosion | Documentation - Roblox Creator Hub

6 Likes

This is just an acknowledgment announcement!

We’ve filed a ticket into our internal database for this issue, and will come back as soon as we have updates!

Thanks for flagging!

2 Likes

Good thinking. Explosions are actually one of the rare exceptions because they destroy themselves shortly after the blast. Any connections to them likewise get disconnected.

A comment could convey that. Additionally, the sample could use a slight update, more particularly parentModel which doesn’t necessary reference a model. Here are the proposed changes:

Custom Explosion
local function customExplosion(position, radius, maxDamage)
    local explosion = Instance.new("Explosion")
    explosion.BlastPressure = 0 -- this could be set higher to apply velocity to parts in reach
    explosion.DestroyJointRadiusPercent = 0 -- joints remain safe
    explosion.BlastRadius = radius
    explosion.Position = position
    
    -- Set up a table to track the hit models
    local modelsHit = {}
    
    -- Listen for contact
    -- Because exposions are destroyed shortly after the blast, the
    -- connection will become disconnected and will not leak memory
    explosion.Hit:Connect(function(part, distance)
        -- Check whether the parent of the hit part is a model
        if part.Parent and part.Parent:IsA("Model") then
            local parentModel = part.Parent
            
            -- Check if this model has been hit already
            if modelsHit[parentModel] then
                return
            end
            
            -- Log this model as hit
            modelsHit[parentModel] = true
            
            -- Look for a humanoid
            local humanoid = parentModel:FindFirstChildOfClass("Humanoid")
            if humanoid then
                local distanceFactor = distance / explosion.BlastRadius -- get the distance as a value between 0 and 1
                distanceFactor = 1 - distanceFactor -- flip the amount so that lower == closer == more damage
                humanoid:TakeDamage(maxDamage * distanceFactor) -- call TakeDamage to respect ForceFields
            end
        end
    end)
    
    explosion.Parent = workspace
end

customExplosion(Vector3.new(0, 10, 0), 12, 50)

(Comments in their own lines are now capitalised to match the style of the latest samples. Really insignificant, but if we’re making changes, there are also two comments to be capitalised in the Non lethal explosions sample.)

Careful with this! Explosions get removed, but not destroyed. That is, they get parented to nil a few seconds later but it doesn’t lock the parent or disconnect the connections to it. OP is correct that the sample contains a memory leak for this reason. We’ll get that updated asap!

4 Likes

Interesting. In such case the summary section could then also be updated to reflect that more clearly. I thought explosions were :Destroy()ed based on this statement:

If an explosion is instanced while the game is running, it will destroy itself shortly afterwards, so they do not need to be cleaned up using the Debris service.

→ Same applies to explosions inserted before the game runs.

So currently it only gets properly cleared when there’s no strong reference and it isn’t connected to the data model. And the explosion in the sample would get collected if it weren’t for this line (local distanceFactor = distance / explosion.BlastRadius) in the callback referring to it.

Thank you for pointing it out! :slight_smile:

1 Like

Thank you for reporting this! We have updated the code sample to destroy the explosion once it is removed.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.