so I’m trying out OOP in Lua for the first time and I have realized that I will probably leak memory by the way I’m scripting this right now.
Code on a server:
local BotObject = BotSystem.CreateBot(“Noob”, 100, workspace, Vector3.new(0,0,0))
CreateBot function in a module:>
BotSystem.CreateBot = function(Name, Health, Parent, Position)
local con
local self = setmetatable({}, Class)
self.Bot = Objects.Bot:Clone()
self.Bot.Name = Name
self.Bot.Humanoid.MaxHealth = Health or 100
self.Bot.Humanoid.Health = Health or 100
if Parent then self.Bot.Parent = Parent end
if Position then self.Bot:MoveTo(Position) end
con = self.Bot.Humanoid.Died:Connect(function()
con:Disconnect()
wait(1)
self.Bot:Destroy()
setmetatable(self, nil)
self = nil
end)
return self
end
How would I have to change things to not leak memory and to make it as efficient as possible?
After the bot dies the the table still exist and I want the bot to be completley removed.
I don’t think setting the metatable to nil helps. And setting self to nil doesn’t do anything either, since it only exists within the given scope anyway.
As long as the bot is no longer referenced anywhere, I think you should be fine.
Even if the bot ends up getting destroyed outside of its health hitting 0, that will still disconnect the con event automatically.
It’s doing that because you’re keeping a reference of it.
It’s kinda like the heisenberg uncertainty principle (not really): By “observing” the bot (keeping reference of it), it doesn’t get garbage collected. But if you stopped observing it, it would get cleaned up.
If you want to check if something’s garbage collected, you can hold a weak reference to it in a table and check the length of the table. For example:
-- utility function
local function getGcChecker(object)
local gcChecker = setmetatable({object}, {__mode = 'v'}) -- let [v]alues be collected by the garbage collector
return function()
return #gcChecker == 0
end
end
-- example usage
local t = {}
local checker = getGcChecker(t)
t = nil -- lose all references to t
print('collected:',checker())
wait(3)
print('collected:',checker())
-- prints:
-- collected: false
-- collected: true
By using a table with weak table references – and by checking the length in order to never reference the object itself – you can observe if the object exists without actually observing the object.