Yes.
It’s mainly the memory that will be most affected, creating so many identical metatables instead of using the same metatable will just overload memory.
Having to create a metatable for each table is often needed when using private properties (properties that cannot be accessible through the table).
Here’s a ModuleScript
containing code to create a table with a method movePart()
which will be associated with a Part
(the Part
is the private property, it cannot be accessed via the table). Each time movePart()
will be called, a Tween
will be created and played to move the associated Part
to its new position.
local TweenService = game:GetService("TweenService")
local Block = {}
function Block.new(part)
local methods = {}
function methods:movePart(target)
local tween = TweenService:Create(part, TweenInfo.new(.2), {Position = target})
tween:Play()
end
return setmetatable({}, {__index = methods})
end
return Block
As you can see, I create a metatable for each call because each metatable need it’s own methods
since each one will have it’s own Part
to move and it cannot be accessed through the table (it’s a private property).
Here’s an example of code using this ModuleScript
.
local Block = require(script.Block)
local block = Block.new(workspace.Part)
while true do
block:movePart(Vector3.new(4*math.random(1, 4), 2, 4*math.random(1, 4)))
task.wait(.5)
end
Actually, using one metatable for all other tables is more a way to avoid overloading memory than a need.
Let’s take the same ModuleScript
that was used previously, except that this time the Part
is no longer be a private property (it will be accessible through the part
field in the table).
local TweenService = game:GetService("TweenService")
local Block = {}
function Block.new(part)
local self = {}
self.part = part
local methods = {}
function methods:movePart(target)
local tween = TweenService:Create(self.part, TweenInfo.new(.2), {Position = target})
tween:Play()
end
return setmetatable(self, {__index = methods})
end
return Block
Here’s what happens.
local Block = require(script.Block)
local blockA = Block.new(workspace.PartA)
local blockB = Block.new(workspace.PartB)
print(getmetatable(blockA) == getmetatable(blockB))
-- false because each block have it's own metatable
Each table still has its own metatable, and that’s a problem, because each call will add a new metatable to memory, and it’s possible to avoid this now that there’s no longer any private property. Here’s what the ModuleScript
should look like instead.
local TweenService = game:GetService("TweenService")
local Block = {}
Block.__index = Block
function Block.new(part)
local self = {}
self.part = part
return setmetatable(self, Block)
end
function Block:movePart(target)
local tween = TweenService:Create(self.part, TweenInfo.new(.2), {Position = target})
tween:Play()
end
return Block
As you can see from the examples, the method I choose will therefore generally depend on whether or not there are private properties.