Parts that fall out of the world are not destroyed

When a Part falls out of the world, you would expect it to be Destroyed and have it’s connections disconnected and the other stuff Destroy does, however, as you can see, this isn’t the case

image
(Test performed by dropping a part out of the workspace)

The print statement is not fired if you instead Destroy the part explicitly
image

This creates a severe memory leak for places that rely on lots of parts falling through the world that have events on them.

Expected behavior

I expect the part to be destroyed the same that calling Destroy on it would when it falls out of the world.

14 Likes

Other test cases

  • Player being removed from the game (Kick, leaving) etc. - Fails test
  • Characters being respawned - Fails test
  • GUIs being removed from the Player on respawn - Passes test
  • Accessories being removed through ApplyDescription - Passes test

The test is actually now just check it’s firing Destroyed and if it’s not, try to

  1. Change and detect a change in a property, this proves events are not being disconnected
  2. Try to reparent it back (cant do this with Player)
3 Likes

Yep this has been in place for a while now, and was responded to here:

Though hopefully it should be fixed now quote:

2 Likes

This is a weird engine quirk, reviving parts that fell out of the world is definitely a hack. While I’m all for backwards compatibility, this is one of those places where I’m skeptical of it because of the memory leak. StreamingEnabled is likely the only place where destroying the part is a bad idea for the time being (even though it would be easy to code around).

I’m hoping to get engineer input here 2 years later because StreamingEnabled is a little more developed instead of reviving a dead thread when the Destroying event didn’t exist

The fix right now is just explicity calling Destroy when AncestryChanged fires with Parent = nil but this also feels really hacky, but it does work for characters and players if done right.

8 Likes

I thought this had been fixed along with the introduction of Instance.Destroying! This behaviour doesn’t make any sense, and feels unintended (like, why is it called FallenPartsDestroyHeight if it doesn’t :Destroy anything?)

Definitely seems like a significant memory leak. +1.

4 Likes

I had no idea this behavior existed and it’s probably causing some unknown slow leaks in our games.
This is probably true for the overwhelming majority of devs as well.

Leaving a landmine like this in the engine is a horrible idea just for the sake of backwards compatibility.

Reminds me of this exploit almost nobody knew about (except exploiters) and was leaving vulnerabilities in nearly every game:

3 Likes

I stumbled upon this by complete accident by doing the tomfoolery that I usually do in Studio. I was just trying to show someone that Destroyed didn’t fire when an instance fell out of the world and then it spiraled into me testing loads of internal removals to check if Roblox is destroying them properly (it wasn’t)

Interestingly it seems to be the older behaviours that still rely on this. It’s not only parts falling out the workspace, it happens to characters respawning and players leaving as well (the player one is quite well known). GUIs being removed or re-apply descriptions do correctly destroy instances

If you want the raw code that I use to test if instances are being removed properly, I like using this (wont work on players, you need to modify it a bit)

local part = workspace.Part

local e = part:GetPropertyChangedSignal("Name"):Connect(function()
  print("oh no it didnt clean up properly")
end)

part.Destroyed:Connect(function()
  print("yay it called Destroy")
end)

part.AncestryChanged:Connect(function(_, p)
  if not p then
    task.wait(1) -- allows Roblox's collector to cycle
    print(e.Connected) -- should return false
    p.Name = "oh no" -- the event above should not fire if this is destroyed
  end
end)
3 Likes

I noticed this the other day as well. My old character model stayed grouped even after I died, and none of the parts inside seemed to be destroyed as they were still parented to the model, inside nil. This behavior might also differ from client-server.

Thanks for the report! We’ve filed a ticket in our internal database.

2 Likes

Seems like this issue was already reported here: FallenPartsDestroyHeight doesn't Disconnect Destroyed Instances with Signals - #6 by ContextLost

1 Like

This topic was automatically closed after 7 days. New replies are no longer allowed.