Destroying is meant to fire before before the instance is parented to nil and its descendants destroyed. According to the documentation: “The Destroying event fires immediately before the Instance or one of its ancestors is destroyed with Instance.Destroy().” However, when listening to Instance.Destroying and then calling :Destroy(), the event handler sees the instance’s parent as nil, even if the handler doesn’t yield.
This sample demonstrates how an Instance being destroyed remains in place until the connected function yields.
local part = Instance.new("Part", workspace)
local function onPartDestroying()
print("Before yielding:", part:GetFullName(), #part:GetChildren())
task.wait()
print("After yielding:", part:GetFullName(), #part:GetChildren())
end
part.Destroying:Connect(onPartDestroying)
part:Destroy()
When running this code on a default baseplate, it does not work.
Expected behavior
I expect the instance to not be parented to nil and its children not destroyed inside the Instance.Destroying handler, as long as the developer doesn’t yield. This matches the expectations set by similar methods like Instance.DescendantRemoving (called before descendant is removed, as opposed to Instance.DescendantRemoved, which is called after the fact)
Ah yeah, I suspected it was because of deferred events. Since deferred events is now the default for new places, I agree Roblox really should fix this. Appreciate the suggestions in the meantime.
Deferred hasn’t accounted for events like this in mind, since Destroying, and AncestryChanged (and other similar events) fire before doing the action on the assumption you’ll do everything before the internal thing performs its action.
I dont want to know what happens with PlayerRemoving client side since that can only run until a yield occurs.
Events like this should really ignore deferred signals since they expect a certain shape (which isn’t respected if you defer it), or the internal action doesn’t happen until the event has actually signalled, which has its own issues.
I would like to add onto this bug report if you don’t mind.
Instance.Destroying does not always seem to fire if a object is destroyed on the server but a client script tries to detect if it’s destroyed.
I sometimes do client-sided logic that needs a clean-up procedure when an object is destroyed but when an object is destroyed on the server the event doesn’t seem to fire on the client.
The .Destroying event does work differently with Deferred signal behavior, this is by design at the moment. As mentioned above, the docs have been updated to reflect this new behavior. That said, we are open to your feedback at the Deferred Engine Events: Rollout Update thread!