Hello! I would like to ask if I call a function that has a local table inside it and call it again, will the elements from the first calling still be around or will it only include the elements from the second calling? I honestly don’t know how to explain it in a clear way so I will send the code I made here:
function collectPlayers()
local pos1,pos2 = (area.Position - (area.Size / 2)),(area.Position + (area.Size / 2))
local region = Region3.new(pos1,pos2)
local playersFound = game.Workspace:FindPartsInRegion3(region, nil, math.huge)
local tplist = {}
for _, v in pairs(playersFound) do
local pl = v.Parent:FindFirstChild("Humanoid")
if pl then
local player = game.Players:GetPlayerFromCharacter(pl.Parent)
if not table.find(tplist, player) then
table.insert(tplist, player)
end
end
end
return tplist
end
local TeleportService = game:GetService("TeleportService")
local gameID = 0
function teleport()
local players = collectPlayers()
TeleportService:TeleportPartyAsync(gameID, players)
end
Here’s what happening and what I’m confused about:
Let’s assume that function teleport() is called and the local variable “players” calls for collectPlayers().
Inside the collectPlayers() function, a table named “tplist” is inserted with a list of players (let’s call them Group A)
Then, collectPlayers() returns with Group A inside table tplist.
After the teleport function() is completed, it is called again. The local variable “players” calls for collectedPlayers() a second time.
Inside the collectPlayers() function, the table is inserted with another list of players (let’s call them Group B)
My question is, once tplist is returned what will be the table’s contents?
Option A = {Group A}
Option B = {Group B} -- this is what I want to happen
Option C = {Group A + Group B} -- this is what I think will happen
Option D = Error
I worry that Option C will happen because this can cause a major bug in my game and then slow down the game’s memory. I hope to hear from you all!
After calling collectPlayers for the 2nd time, before returning, tplist contains “Option B”, or group B. Once the function returns, tplist is most likely nil. If there is a variable with the same name in the surrounding scope, then that variable will be unaffected.
Since you define tplist as a local variable inside collectPlayers, it goes out of scope when the function returns. Read more here, especially the 3rd code example on the page.
This actually makes sense but assuming that calling collectPlayers() for the 2nd time returns nil, doesn’t it mean that calling it the first time would also return nil?
Put simply the variable is local to the function so will be created each time the function runs. ie a new table each time. It would only return a table with the players or an empty table.
No, it returns group B the 2nd time (and group A the 1st time), but the variable called tplist is out of scope once the function returns, meaning that if you try referring to it, you get nil.
Another tip (I found this out not too long ago)
" __mode Used in weak tables, declaring whether the keys and/or values of a table are weak. NOTE: References to Roblox instances are never weak. Tables that hold such references will never be garbage collected."
Ref Roblox Metatables
I’d like to clarify that this is only the case with tables you currently have a reference to, not for every table you make.
local part = Instance.new("Part")
local tab = {part}
part:Destroy()
Will prevent part from being released effectively forever as we never lose the reference to tab. Whereas in this example
local function f()
local part = Instance.new("Part")
local tab = {part}
return tab
end
f()[1]:Destroy()
Here we do something similar but we drop the reference to the entire table as we index f() directly instead of assigning it to a variable. While tab still contains a strong reference to part, and so would not let part be released, there isn’t a strong reference to tab anymore (or indeed any reference) so the gc will happily collect the entire table including roblox objects held inside.
So if I understand this properly, to effectively cut a strong reference between an instance and a table, you need to remove the instance from the table rather than directly remove the instance? I might be wrong though since I’m really new to tables.
When you have an instance in a table you want to destroy, you must also remove the instance from the table like so.
local part = Instance.new("Part")
local tab = {}
tab.p = part
part:Destroy()
print(tab.p) --part still exists
tab.p = nil
print(tab.p) --every reference is dropped so part is now fully destroyed
Or, if you use it as a key not a value.
local part = Instance.new("Part")
local tab = {}
tab[part] = true
part:Destroy()
print(tab[part]) --part still exists
tab[part] = nil
print(tab[part]) --every reference is dropped so part is now fully destroyed