Lets say I have a table local tbl = {}
, and lets say that in that table we stored a part table.insert(tbl, workspace.Part)
. If the server destroyed that part workspace.Part:Destroy()
, would it be good practice to remove the object from the table to prevent memory leaks table.remove(tbl, 1)
, or should we not remove it from the table, and instead let roblox garbage collect it?
I believe the table would return nil, wouldn’t it?
Cause the table holds a reference to the part.
Therefore, the only thing you need to worry about, is removing it from the list to avoid getting nil values
Destroy sends an object to garbage collection.
But wouldn’t it also return nil
if it is removed from the table?
If it’s not in the table, or the edit: game enviroment It’s nil.
So either way its gonna be nil
?
Yes. But if left in the table, it will mess it up if you’re storing and deleting objects. Best to just clean up the table.
It’ll mess up depending on how you’re using it. But for best practices, just clean it up with a custom event handler.
Roblox will not collect a destroyed part until all references to it don’t exist anymore. This means that if the part is referenced directly or indirectly in any variable, it will stay in memory and will not be deleted.
Whenever you call :Destroy
on any instance, all it does is parent the instance to nil
, lock the .Parent
property, and disconnect all event connections. It does not explicitly remove it from memory.
What counts as a reference?
dictionary[key] = Part
table.insert(array, index, Part)
variable = Part
You can destroy these references by making what is storing the part nil
:
dictionary[key] = nil
table.remove(array, index)
-- OR
dictionary or array = nil
variable = nil
Keep in mind that you would have to do this for all references if the part is stored in multiple places.
If you’re using a local variable, the reference to the variable will be destroyed when they go out of scope:
do -- create a new scope
local variable = Part -- make a reference to the part
end -- reference is destroyed, since it's now out of scope!
Functions use the variable itself as a reference and doesn’t save it there in the function:
local Part = -- your part
function fn()
print(Part.BrickColor.Name)
end
fn() --> Medium stone grey
Part = nil
fn() --> errors
Connections to events are known to cause memory leaks, but it gets very technical:
Destroyed parts can still be referenced by variables in the meantime though, which means you can access their properties as well as methods and events but who cares about that:
Part:Destroy()
-- this is possible
local storedColor = Part.Color
Part = nil
So that block of code can be used to remove the reference in the table?
Yeah, but for arrays I would use table.remove
. It will move all the other elements back one to keep the behavior of an array.
The dev hub has an article about what arrays are, and the other kinds of tables too: Tables | Documentation - Roblox Creator Hub
I have one question. If I have a table inside a table like local table = {anotherTable = {}}
How would I remove something in the “anotherTable
” table? Would I use something like this: table.remove(table[1], 1)
?
In that specific example, I would use table.remove(table.anotherTable, 1)
, since the anotherTable
is stored in the key of the same name, but basically, yes.
You would also have to name the base table something different, just because table
is already taken, e.g. local tabl = ...
What about if the table inside the other table was created like so: Table[#Table + 1] = {Inst1, Inst2}
How would I delete Inst1
, and Inst2
?
(Unless I am dumb, and that is not a table inside another table)
If you have access right after that line was made, you could just use table.remove(Table)
, and it will automatically remove the last element from Table
, which is the instance array.
If you don’t, you can store an index of the new array and remove it using table.remove
that way:
local index = #Table + 1
Table[index] = {Inst1, Inst2}
-- later,
table.remove(Table, index)