New Player and Character Destroy Behavior Enabled by Default


Hello everyone! We wanted to give you a quick update on New Player and Character Destroy Behavior.

Background

Late last year we announced New Player and Character Destroy Behavior, a change to reduce memory leaks on the server related to instances and signals connected to Player and Character instances and their children.

As a quick reminder, our last announcement introduced the following behavior:

  • When a player leaves the experience, the Destroy method is called on the Player Instance on the Server. This task is deferred and occurs after bound event connections are invoked, including PlayerRemoving.
  • When a player’s character is removed, the Destroy method is called on the Model Instance on the Server. This task is deferred and occurs after bound event connections are invoked, including CharacterRemoving. Replication of the destroy follows the regular rules and place settings, as if the Destroy call was manually made in the CharacterRemoving callback.

Given the impact of this feature we decided to give developers ample time to adapt to the new behavior.

Updating the Default: Disabled to Enabled

We are seeing many experiences switching to this new behavior. We’re also seeing numerous discussions across the DevForum with Creators recommending this mode as a solution to problems other Creators are having. Great!

Given this organic adoption and excitement: we are now switching the value of Default mode of the PlayerCharacterDestroyBehavior Workspace property from Disabled to Enabled.

And of course, if you are seeing issues with new behavior, you can temporarily disable it by setting the property value to Disabled.

If the new behavior presents problems for which you cannot find a workable solution, leave a comment here in this topic!

Please note that we are aiming to remove the property and the ability to opt-out altogether in Q1 2025 so it’s important that we resolve all issues before then.

114 Likes

This topic was automatically opened after 10 minutes.

I’m quite happy that this is happening, but is there any update to the fact that this behavior doesn’t work on the client at all? I made a bug report over 7 months ago and I’ve received no response. I get that the main functionality is supposed to be server sided, but the fact that it doesn’t work on the client is a little ridiculous.

14 Likes

Sorry for the missing response in the original topic.

The feature was intended to focus on the server-side because servers are usually running for way longer that clients and the impact is bigger than on an individual client.
However, we have introduced a change to Destroy replication before that to mirror the destruction on the Client: Destroy() Can Now Replicate to Clients

We are going to check for the reasons why this might not be replicated in the same way.

16 Likes


so basically it can’t yield now? or well, it can but it won’t work

though it was always mentioned that the “player” object that using this method apparently isn’t reliable

would it also mean that there’s a chance that the player can be nil, or what would “deferred” mean in this

9 Likes

You can still create references to Player child instances before you yield and use them after.
All properties are still accessible (except for those related to instance placement in the DataModel tree).

Instances will be parent-locked to nil though, so additional changes might be required if there was an intention to re-use those instances somehow.
You can still clone them individually after the yield in destruction or as a sub-tree before the yield.

Edit: player argument will never become nil.

16 Likes

Interesting, very interesting…

3 Likes

Would not be possible to yield the destruction of the player for a few seconds so developers could code when the player is leaving? Some things like backpack saving may be affect by this change.

7 Likes

Are there any plans to eventually update fallen parts behavior, so that non-character associated fallen models will also be destroyed, rather than merely removed? The Workspace property name ‘FallenPartsDestroyHeight’ can be deceptive in this way.

7 Likes

if this gets enabled, what will happen of we still manually destroy player/character? (didnt update the script)

3 Likes

I don’t imagine there’d be any problems here. Destroying the same instance multiple times, has generally always been without issue, and should be perfectly safe.

5 Likes

Would this be the reason why player.AncestryChanged() no longer works for saving data?

2 Likes

This change is very likely to cause that.

Can you describe your save process setup in more detail so we can test that flow and suggest a workaround?

3 Likes

Does this mean you are no longer automatically destroying the player instantly? (Woo data saving problems solved)

If I may make a suggestion, just do what @P7_Error said, as then it can still be destroyed, but then we have time to make changes, a long with that maybe allow us to change the time before the player is destroyed, so then we really aren’t limited.

Anyhow hope you fix the problems with this feature, as then I dont have to manually do it lol

1 Like

Hi! I create a PlayerData folder within each Player, which contains various subsets, and within those subsets, there are further subsets depending on the type of data being stored, such as Inventory, Loadout or Settings. Some folders (usually the last child) have attributes assigned to them.

Upon the PlayerRemoving event, I serialize the entire PlayerData folder, including all its descendants, into a table and save it to DataStore. However I can’t reference the descendants during the PlayerRemoving event.

One approach I considered was saving the data into a table using custom read/write functions, but this would require a significant amount of recoding.

Is there a way to reference or replicate the PlayerData folder upon the PlayerRemoving event? Alternatively, would a change in the process itself be more optimal? I’d appreciate any advice on improving this workflow.

3 Likes

Is there any convincing reason as to why these destroyed instances need to have their descendants parented directly to nil in the first place? An unreferenced instance tree outside of the datamodel, is surely still perfectly eligible for GC. It seems as though we could have a variant of destroy that still treats these niche memory leakage concerns, without introducing unnecessary conflicts with the old player/character removal behavior, which only set the parent of the root instance to nil.

Hi, Why not just Clone() your PlayerData folder then reference the values in the cloned instance? It seems to work in my tests. Looks like it could be a good way to deal with this if you have everything in a Player.PlayerData folder (unlike myself) :frowning: .

1 Like

i don’t see how this is an issue, keep a table with updates that reflect whenever the backpack changes then save that, don’t do it when the player leaves… that’s how you get duplication glitches :sweat_smile:

1 Like

Different developers code differently, not to mention how simple games used to be. Making the setting default to be Enabled is not the issue, but sunsetting it completely.

Also this same argument could be used for why this implementation was added in the first place, since you could possibly code the destruction of the player by yourself and clear all cache.

The backpack was used as an example, since it’s the most used type of code that would normally have this issue, but you can also refer to Values that are unique to a player, Folders with values that are used as (although poor) saving systems, you cannot simply say that the whole platform should adhere a change just because it can be coded in a different way.

Talking about duping, until a year ago (not sure now) you could enter two different servers with two different instances of the Roblox Player, making any protection utterly useless since the same account could be at different servers at the same time. Obviously this could be fixed with code, but relied completely on the developer themselves.

1 Like

Can the property instead be changed to a number that is the delay before the player and characters are destroyed

2 Likes