Do unused clones cause memory leaks?

Say for example, in a respawning script for an npc i have, it clones the npc for future use if the npc needs to respawn, but then the npc as a whole gets destroyed later, would the clone still exist and build up over time with me reusing the script, therefore causing a memory leak?

1 Like

The clone will still exist, taking up memory. If you keep creating new clones and don’t clean them up, this will indeed lead to increased memory usage over time.

When you clone an object in Roblox using Instance:Clone(), it creates a new instance in memory. If the clone is left unparented, it technically still exists in memory.

(edit made it a bit more readable.)

If you don’t have any references to it (local ClonedNPC = urclonednpc OR local Table = {ClonedNPC = urclonednpc}) and no connections to the npc and it’s children (ClonedNPC.Humanoid.Dead:Connect()) then it will be garbage collected automatically if it’s parented to nil, otherwise it will stay until you Destroy() it

3 Likes

it is referenced in the respawning script of my npc in case it needs to be used however it is always parented to nil

Then it will continue to exist in memory. In order for the instance to be automatically cleared from memory by the garbage collector, it must have no references—with the exception of weak references—and have no parent. Your script does not use a weak reference, nor should it in this scenario

1 Like

If the clone is not parented to nil, or if there is active references to it in a script (stored in a table, referenced by variable in an active thread), then it will cause a memory leak.

If the NPC script is inside the NPC while it’s destroyed, the script will also be destroyed. Meaning it will disconnect all connections and end that thread, so in most cases that would not cause a memory leak.

2 Likes

so that means i dont need to worry about it then? because this is basically my case since the way my game works is having a rounds system of a killer npc spawning but after some time it despawns but it has the respawn script in case it somehow dies (the respawn script gets destroyed too when the npc despawns, so im assuming that means all the references to that specific clone are destroyed?)

So, firstly, “memory leak” is a pretty technical term, so I would double-check that that is the correct wording for your particular issue. As @randomlletters said, garbage collection (a background process that runs alongside every Lua/Luau program) saves us from problems like memory leaks; you can check the Lua docs for more info, it’s cool stuff.

However, they can still occur if we aren’t careful with our object references; here’s a helpful excerpt from the Unity team:

Memory leaks typically occur due to one of two issues:

  • An object that is not released manually from memory through the code.
  • An object stays in memory because of an unintentional reference.

To determine whether this is happening in your code, it’d be helpful for you to post the script in question.

Helpful note. I hadn’t heard of Lua’s weak references/weak tables before. Thanks!

1 Like
local Copy = script.Parent:Clone()
local NPC = script.Parent
local Humanoid
for i,v in pairs(NPC:GetChildren()) do 
	if v:IsA('Humanoid') then 
		Humanoid = v 
	end 
end

if Humanoid then
	Humanoid.Died:Connect(function()
		wait(5)
		Copy.Parent = NPC.Parent
		Copy:MakeJoints()
		NPC:Destroy()
	end)
else
	warn('Cannot find Humanoid in Respawn Script!')
end

pretty much this logic applies to all my respawn scripts even if theyre coded a bit differently

Destroying the NPC destroys the script, which in turn destroys its memory; since no other script can possible hold a reference to Clone before it’s deployed, the clone will be erased with the script. There is no need for you to create the clone until the NPC dies, however.

On a side note, you can replace this code with a more optimal solution:

local Humanoid
for i,v in pairs(NPC:GetChildren()) do 
	if v:IsA('Humanoid') then 
		Humanoid = v 
	end 
end

Alternative:

local Humanoid = NPC:FindFirstChildOfClass("Humanoid")

Yeah, if that’s the case you should be good.

I don’t know if I would call that a memory leak… Sounds more like allocated memory. Use a garbage collection technique to remove unused NPCs like, game.Debris:AddItem()… Then re-create a fresh one if needed.

If you clone an instance like this.

local object = workspace.Model:Clone()

It will continue to exist until it is :Destroy()'d.

By executing this line of code, an object is created and parented in nil where it shall remain forever until you decide to do something with it.

I’m not certain if it eventually gets garbage collected once the script that created the clone is destroyed, but I honestly wouldn’t rely on that behavior.

If you want to respawn an NPC, I recommend you keep the NPC in ReplicatedStorage or ServerStorage and only clone it the moment it needs to respawn.

After that you can simply set it’s CFrame and whatnot to the location where it needs to respawn.

This should prevent potential memory leaks.