How do I check that a part was :Destroy()'ed?

How do I check that a part was :Destroy()'ed?. Just checking if the part’s Parent is nil doesn’t work because it would also include parts which were parented to nil directly via script.

I could possibly do a check by parenting the part to Lighting (or somewhere else that the player can’t see) and checking if it gets forcefully parented back to nil, but I was hoping that there would be a better way.

If you’re curious, I’m writing a module that generates and maintains list of parts with certain tag(s) (for tag-based ignore lists and whitelists, for example), and I’m wary of cases where parts are recycled.

5 Likes

There is not a way to do this currently.

1 Like

Okay, it turns out :GetInstanceAddedSignal() fires whenever the part is either is parented to nil or is :Destroy()'ed anyway, so it turns out this isn’t necessary. Huh.

1 Like

Here’s a hacky way to do it:

local function Destroyed(x)
	if x.Parent then return false end
	local _, result = pcall(function() x.Parent = x end)
	return result:match("locked") and true or false
end

local x = Instance.new("Part")
print(Destroyed(x)) -- false
x:Destroy()
print(Destroyed(x)) -- true
39 Likes

You can always also just return the boolean of the pcall; I’m not aware of any other errors interrupting reparenting (besides RobloxLocked but that’s evadable on its own).

1 Like

If it doesn’t error that its parent is locked then it will error because I’m trying to set its parent to itself.

1 Like

I wasn’t aware of such a case erroring, although I’ve probably never tried it myself besides the odd missclick and window popup in Studio.

3 Likes

Another solution is to give it a special tag with CollectionService before being destroyed, and then check if they still have that tag. When a part is destroyed, all its tags are removed. This is also the way to implement a “Destroyed” event, rather than continuously checking if you can still set its parent.

6 Likes

Couldn’t you just do:

local destroyed = not part:IsDescendantOf(workspace)

EDIT: This check seems to only work on the client, if the :Destroyed was called on the part via server.

2 Likes

If the part is parented to ReplicatedStorage, then that code wouldn’t work.

If you instead check that it’s a descendant of game (or that its parent is nil), it still wouldn’t work. You can parent things directly to nil and still reparent them back to workspace afterwards, but when you :Destroy() something, you can’t set its parent afterwards anymore.

3 Likes

What I’m doing in my case is that I’m creating a part on the workspace.

Then on a loop in the client, I’m using that code

to detect if it’s destroyed. It never gets parented to nil or anywhere else besides workspace.

Do you see anything wrong with it?

1 Like

Depends how you’re doing the loop. This would be the best.

while true do
    part.AncestryChanged:Wait()
    if not part:IsDescendantOf(game) then
        break
    end
end

-- destroyed at this point

Or you can just connect AncestryChanged itself.

2 Likes

Why does this work on the client but not on the server?

1 Like

It does, what are you detecting?

1 Like

Well if something like this works

part.AncestryChanged:connect(function()
if (not part:IsDescendantOf(workspace)) then
end
end)

why would we need this:

1 Like

You don’t need that.

1 Like

That only detects when the part was parented to nil, not when it’s destroyed.

waffle’s way of checking if a part is destroyed is pretty much the only way.

1 Like

No it works when it’s destroyed i just tested it

EDIT: nvm

1 Like

How often do you need to know when something is destroyed specifically instead of just when it’s out of the game world?

Inaccurate information

If you truly want a destroyed signal, you can use CollectionService.

CollectionService:AddTag(instance, "__DESTROYED")

…then…

CollectionService:GetInstanceRemovedSignal("__DESTROYED", function(instance)
   -- Called when anything with __DESTROYED is destroyed
end)

To check if it’s destroyed, CollectionService:HasTag(instance, "__DESTROYED").

But you never really need to do that. Again, how often do you need to know when specifically :Destroy() has been called?

2 Likes

So say that my part should only be parented to the workspace, and if it’s not, it’s destroyed in my game (bc I won’t ever parent the part to anything else other than workspace).

So would this code suffice for my scenario?

part.AncestryChanged:connect(function()
if (not part:IsDescendantOf(workspace)) then
--stuff
end
end)
1 Like