Do instances in a table get removed after being destroyed?

Hello, I am using tables in my game and the items in it are instances. I’m wondering if the table items get removed after being destroyed in workspace. Anybody know about this?

1 Like

I think it gets removed once you dystroy it, but uh i would say just copy and paste it to be on the safe side

I need the items to be removed when deleted

i think it’ll just become nil u could try using DescendantRemoving or ChildRemoved to know when they get deleted and then manually delete it from the table

Sorry I didn’t mention this before :sweat_smile:. I’m trying to count the players in a match, so I’m assigning the item to the player. The item’s are BoolValues. So, I can’t do that really since a player might leave.

Are the instances in the table the bool values and are those the things you need to know when they get deleted

The answer is no. Instances will remain in the table. Destroying only sets and locks the parent to nil. You’ll have to manually remove it from the table at that point. Nil objects will only be garbage collected when there are no more references to it (such as a table or a variable).

6 Likes

Well, the players will sometimes leave. This causes issues because I can no longer access the item.

You still have access via the array. Either you can go through the array and remove any instance with a nil parent, or you can hook up a function to remove a player when they leave the game (via the player removing event).

That’d be hard since I’m putting it in a function that also determines the game length. Here is my code:
Screen Shot 2022-07-19 at 4.28.31 PM
vTags are the table items. NSplayers is the players who joined, I am checking if the players vTags are there or not/If the players are there or not.

You can store a table inside of a table to form a dictionary. It would actually be easier if you just did something like NSplayers[player.Name] = {table}. Then when that player has left, just set it to nil instead of a table. Though I should mention that it will show as having 0 items because it’s no longer an array. But you can still iterate through it with a for pairs loop.

Also please post code using markdown instead of taking a screenshot:

```Lua
print(‘Hello world!’)
```

print('Hello world!')

If you just want to count players in the game, do this:

playerService = game:GetService("Players")
local players = playerService:GetPlayers()
local playerCount = #players

It’s as easy as that. Run that once a second or so in your main loop.

I am using intermission, and game. I have to count the players in the match, not every single one in the game.

I tried that, and it didn’t work very well. Here is my full code;

wait(1)
ReplicatedStorage = game:GetService("ReplicatedStorage")
Players = game:GetService("Players")
gameStatus = ReplicatedStorage.gameStatus

local function restartGame()
	script.Disabled = true
	wait()
	script.Disabled = false
end

maps = {
	ReplicatedStorage.ForestMap, 
	ReplicatedStorage.WorshipMap, 
	ReplicatedStorage.NeonMap
}
while true do
	gameStatus.Value = "Waiting for Players"
	
	repeat wait() until Players.NumPlayers > 1
	
	gameStatus.Value = "Intermission, Time Left: "
	
	local timeLeft = 15
	for i = 1, timeLeft do
		gameStatus.Value = ("Intermission, Time Left: " .. timeLeft)
		wait(1)
		timeLeft -=1
	end
	
	local chosenMap = maps[math.random(1, #maps)]
	
	chosenMap.Parent = game.Workspace
	
	local NSplayers = {}
	
	for i, v in pairs(Players:GetPlayers()) do
		table.insert(NSplayers, v)
	end
	for i, v in pairs(NSplayers) do
		v.Character:MoveTo(math.random(0, 30), 30, math.random(0, 30))
		
		local sword = ReplicatedStorage.ClassicSword:Clone()
		sword.Parent = v.Backpack
		
		local vTag = Instance.new("BoolValue", v)
		vTag.Name = (v.Name .. "vTag")
	end
	local playersLeft = {}
	
	for i, v in pairs(NSplayers) do
		table.insert(playersLeft, v.vTag)
	end
	
	for i, v in pairs(NSplayers) do
		local character = v.Character
		
		if not character then
			--They left
			table.remove(playersLeft, (v.Name .. "vTag"))
		end
		if v:FindFirstChild("vTag") then
			--They are alive
		else
			--They are dead
		end
		if playersLeft == 1 then
			gameStatus.Value = (playersLeft[1].Name .. "won!")
			playersLeft[1].leaderstats.Wins += 1
			playersLeft[1].Character.Humanoid.Health = 0
			restartGame()
		elseif playersLeft == 0 then
			gameStatus.Value = "Nobody won"
		end
	end
end
--[[while true do
	wait(2)
	game:GetService("Lighting").ClockTime = 14
	gameStatus.Value = "Waiting for Players"
	
	--repeat wait() until Players.NumPlayers > 1
	
	gameStatus.Value = ("Intermission, Time Left: " )
	local timeLeft = 15
	for i = 1, timeLeft do
		wait(1)
		timeLeft -= 1
		gameStatus.Value = ("Intermission, Time Left: " .. timeLeft)
	end
	local NSplayers = {}
	for i, v in pairs(Players:GetPlayers()) do
		table.insert(NSplayers, v)
	end
	local chosenMap = maps[math.random(1, 3)]
	chosenMap.Parent = game.Workspace
	wait(1)
	
	gameStatus.Value = "Game In Progress: 90"
	
	for i, v in pairs(NSplayers) do --Getting the Players in the game
	if chosenMap == maps[1] then
	game:GetService("Lighting").ClockTime = 14
			if v.Character then
				v.Character:MoveTo(Vector3.new(math.random(1, 2),30,math.random(1,2)))
				local sword = ReplicatedStorage.ClassicSword:Clone()
				sword.Name = "Sword"
				sword.Parent = v.Backpack

				local vTag = Instance.new("BoolValue")
				vTag.Parent = v.Character
			else 
				table.remove(NSplayers, v)
			end
	elseif chosenMap == maps[2] then
			game:GetService("Lighting").ClockTime = 14
			if v.Character then
				v.Character:MoveTo(Vector3.new(math.random(1, 1),30,math.random(1,1)))
				local sword = ReplicatedStorage.ClassicSword:Clone()
				sword.Name = "Sword"
				sword.Parent = v.Backpack

				vTag = Instance.new("BoolValue")
				vTag.Parent = v.Character
			else 
				table.remove(NSplayers, v)
			end
			
	elseif chosenMap == maps[3] then
			game:GetService("Lighting").ClockTime = 1
			if v.Character then
				v.Character:MoveTo(Vector3.new(math.random(30, 30),30,math.random(30, 30)))
				local sword = ReplicatedStorage.ClassicSword:Clone()
				sword.Name = "Sword"
				sword.Parent = v.Backpack

				local vTag = Instance.new("BoolValue")
				vTag.Parent = v.Character
			else 
				table.remove(NSplayers, v)
			end
			
	end
		wait()
	end
--Music
	local music = Instance.new("Sound")
	music.Playing = true
	music.SoundId = "rbxassetid://1839525927"
	music.Parent = game.Workspace
	--GameInProgress
	local gameTime = 90
	for i = 1, gameTime do
		for x, player in pairs(NSplayers) do
			if player then
				local character = player.Character

				if not character then	
					--They left
				elseif character:FindFirstChild("vTag") then
					--They are alive
				else
					--They are dead
					character:WaitForChild("vTag"):Destroy()
					if character:FindFirstChild("vTag") then
						character.vTag:Destroy()
					end
				end
			end
		end
	end
	gameStatus.Value = ("Game In Progress: " .. gameTime)
	if #NSplayers == 1 then
		gameStatus.Value = (NSplayers[1].Name .. " is the winner!")
		NSplayers[1].leaderstats.Wins.Value += 1
		NSplayers[1].Character.Humanoid.Health = 0
		game:GetService("Lighting").ClockTime = 14
		chosenMap.Parent = ReplicatedStorage
		music:Destroy()
		wait(3)
		restartGame()
	elseif #NSplayers == 0 then
		gameStatus.Value = "Nobody won"
		game:GetService("Lighting").ClockTime = 14
		chosenMap.Parent = ReplicatedStorage
		music:Destroy()
		wait(3)
        restartGame()
	end
wait(0.5)
end]]--

The commented out code is my old backup code.

You’re using a lot of extra code. You only need one table to keep track of the players mid-game. Just get all the players at the start and remove them from the same table as they leave. Also I wouldn’t recommend using the disabled property to restart a round. You should use functions instead. You should also use WaitForChild instead of just putting a random wait at the top of the script. Lastly, for all of your waits, you should be using task.wait now.

Ok, it doesn’t need to be complicated. You would still use a table but you aren’t storing the reference to an instance in that table. Just use the player’s userId which is an integer that is guaranteed to be unique for each player in the game.

local playerService = game:GetService("Players")
local playerMatchTable = {}

local function addPlayer(player)
	playerMatchTable[player.UserId] = true
end

local function removePlayer(player)
	playerMatchTable[player.UserId] = nil
end

local function getPlayerCount()
	return #playerMatchTable
end

playerService.PlayerRemoving:Connect(function(player)
	removePlayer(player)
end)

That’s all there is to it for keeping track of players within a match. As each player enters the match, call addPlayer. As they leave the match, call removePlayer. If the player leaves the game, the event handler will take care of that.

Hope this helps.

But how could I detect if the player left before I check all the players? I’m doing

for i, v in pairs(myplayersvariable) do
local character = v.Character
if  not character then
-- they left
end
end)

You’d remove the player from the table as soon as they leave the game using PlayerRemoving. You don’t need to do anything else.

i know this topic is old already but incase of other new devs asking the same thing it’s a NO on my part. i’ve tried it storing an instance to the table then doing the property change signal ‘parent’ printing the table then another print 2 seconds later, instance is still in the table.

(i have not tried it on live testing but on studio i did.)