STRANGE behaviour!

This might be because the player’s instance leaving is yielded by a wait(1).

No, you can’t halt/yield the Player Instance from leaving.

In studio it seems to happen randomly.


But this makes absolutely no logical sense whatsoever.

1 Like

It could also be caused by the finnicky behaviour of game:BindToClose on studio though, as explained by @MSYGamingTV

It would be impossible to test for this outside of Studio, as server shutdown means that no console logs are kept. Even if BindToClose were a bit unpredictable, why would it fire after Player.PlayerRemoved fired, and still not be able to index the player list?

You can still use webhooks to send a string everytime LogService.MessageOut is fired to your server. In that way you can see what it prints.

Y’know what, screw it.
Here’s a workaround:

Okay, so first, make a Folder in ReplicatedStorage, and name it Players.

Then, add this Script into ServerScriptService:

local playersfolder = game.ReplicatedStorage:WaitForChild("Players")
game.Players.PlayerAdded:Connect(function(player)
	local plrtoken = Instance.new("Folder", playersfolder)
	plrtoken.Name = player.Name
	print("Token added for", player.Name)
end)

game:BindToClose(function()
	print(#playersfolder:GetChildren())
	for _, player in pairs(playersfolder:GetChildren()) do
		print("Player ", player)
	end
end)

I did something like this in a game where i made a player token to save data. Mabye it will work for you.

I ran a test using DataStores on a studio test and an actual server, and the bug still occurs, which means it doesn’t have anything to do with the fact that studio isn’t working. Strange.

1 Like

I’m not looking for a workaround, as I’ve stated.

Perhaps I should report it as a bug?

Why do you need to create instances instead of just using a table?

--//Services
local Players = game:GetService("Players")

--//Tables
local playerTable = {}

--//Functions
Players.PlayerAdded:Connect(function(player)
	table.insert(playerTable, player.Name)
end)

Players.PlayerRemoving:Connect(function(player)
	table.remove(playerTable, table.find(playerTable, player.Name))
end)

game:BindToClose(function()
	print(#playerTable)
end)

That is another way, but I made instances for a game that saved data with them.

Honestly I don’t know how I can help then. From what it seems, game:BindToClose() runs after Player.PlayerRemoving(), so there is no way to get the player instance when it’s gone.

Hence the reason why I made a player token instead. I had this issue before where I tried to access player instances that didn’t exist when I ran game:BindToClose()!

For the final time, I am NOT looking for a workaround. Read the title.

Ok so I found something: I force shut down a server I was in and it saved the number of players PROPERLY. This means that :BindToClose() will run either when all players leave the game, or when a server is shut down

When it’s called via all players leaving, there are no players left.

When it’s called via shutdown, it still has instances of the players.

2 Likes

Exactly what I thought too. I don’t have the Regular role, so I cannot submit a bug report. I will ask others.

But there is nothing but a workaround! As @MSYGamingTV said, player instances are preserved ONLY on force shutdown! Also, I don’t know if this is a bug. But, you can submit it somehow anyways.

Also, I find that in the primary post, there is nothing stating about no workarounds. Yes, you did put it in a post, but that still doesn’t mean it’s in the title.

tbh I dont think this is a bug. BindToClose is designed to carry out any extra procedures when a server shuts down, which purposely only occurs when all players are removed or a shutdown occurs. This function is mainly designed to, for example, save everyone’s progress incase of a shutdown.

Didn’t he just say it was intended behaviour?

The problem is that Player.PlayerRemoved fires after the bound function finishes executing, meaning that the player list should still be intact. Its not - in the case of single-player leaving.