Removing the table from metatable

First time trying to write the oop style module here
is there a way to remove the exisiting table from the metatable once the character is dead?
I’d imagine leaving them there after the character no longer exist might cause the memory leak issue

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SimplePath = require(ReplicatedStorage.Modules.SimplePath)

local Wanderer = {}

Wanderer.__index = Wanderer

function Wanderer.new(char:Model)
	local self = setmetatable({}, Wanderer)
	self.AI = char
	self.Cooldown = 5
	self.Health = 20
	self.Speed = 10
	
	local Hum = char:WaitForChild("Humanoid")
	Hum.WalkSpeed = self.Speed
	Hum.MaxHealth = self.Health
	Hum.Health = Hum.MaxHealth
	
	if self.AI.PrimaryPart ~= nil then
		self.AI.PrimaryPart:SetNetworkOwner(nil)
	end
	
	return self
end

function SelectNode(NodesFolder:Folder)
	return NodesFolder:GetChildren()[math.random(1, #NodesFolder:GetChildren())]
end

function Wanderer:Remove()
	-- ???
end

function Wanderer:Start()
	if self.AI.PrimaryPart == nil then return end
	local Target = SelectNode(workspace.PathNodes)
	local Path = SimplePath.new(self.AI)
	Path.Visualize = true
	Path.Blocked:Connect(function()
		Path:Run(Target)
	end)
	
	Path.WaypointReached:Connect(function()
		Path:Run(Target)
	end)

	Path.Error:Connect(function(errorType)
		Path:Run(Target)
	end)
	
	Path.Reached:Connect(function()
		task.wait(self.Cooldown)
		self:Start()
	end)

	Path:Run(Target)
end

return Wanderer

Yes, having instances tied to a table will most likely prevent it from being GCed.

I highly recommend using ECS over OOP since such situations almost never happen and don’t force you to look at Luau Heap for debugging, and it gives direct access to integrate functional programming with ECS.

--!strict
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SimplePath = require(ReplicatedStorage.Modules.SimplePath)
local PathNodes = workspace.PathNodes
local Wanderer = {}

Wanderer.__index = Wanderer
type Wanderer_Data = {
	AI:Model;
	Cooldown:number;
	Health:number;
	Speed:number;
}
type Wanderer = setmetatable<Wanderer_Data,typeof(Wanderer)>

local function SelectNode(NodesFolder:Folder)
	return NodesFolder:GetChildren()[math.random(1, #NodesFolder:GetChildren())]
end

function Wanderer:Remove()
	-- ???
end

function Wanderer:Start()
	if self.AI.PrimaryPart == nil then return end
	local Target = SelectNode(PathNodes)
	local Path = SimplePath.new(self.AI)
	Path.Visualize = true
	Path.Blocked:Connect(function()
		Path:Run(Target)
	end)

	Path.WaypointReached:Connect(function()
		Path:Run(Target)
	end)

	Path.Error:Connect(function(errorType)
		Path:Run(Target)
	end)

	Path.Reached:Connect(function()
		task.wait(self.Cooldown)
		self:Start()
	end)

	Path:Run(Target)
end

return function(char:Model):Wanderer
	local self = {
		AI = char;
		Cooldown = 5;
		Health = 20;
		Speed = 10;
	}::Wanderer_Data


	local Hum = char:WaitForChild("Humanoid")::Humanoid
	Hum.WalkSpeed = 10
	Hum.MaxHealth = 20
	Hum.Health = 20

	if char.PrimaryPart then
		char.PrimaryPart:SetNetworkOwner(nil)
	end
	Hum.Died:Once(function():()
		table.clear(self::any)
	end)

	return setmetatable(self,Wanderer)::Wanderer
end
1 Like

oh wow this feel like a different style of module entirely I’ll have to study this
but you also give me the answer to my solution so thank you so much

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.