I’m gonna assume you’ve got basics down for metatables.
They are generally only used when you want a table to have fancy behaviour, such as for indexing items not inside the original table.
One of the most common use-cases for this indexing feature is OOP (Object Oriented Programming), which essentially means thinking of tables as objects. Here’s an example of that:
local Weapon = {} -- This is the sub-class which holds generic data and functions for the weapon objects
Weapon.__index = Weapon -- This is makes the `Weapons` table be searched as well when your table is accessed
function Weapon:Attack()
print(`Weapon "{self.Name}" is attacking`)
end
local Sword = {}
Sword.Name = "Iron Sword"
Sword.Damage = 20
Sword:Attack() -- This will error, since no "Attack" function is withing the `Sword` table
setmetatable(Sword, Weapon)
-- This will no longer error, as even tho this function isn't in the `Sword` table,
-- the metatable's `__index` table will still be searched searched as well
-- and within it the function exists
Sword:Attack()
The reason this is useful is that you don’t need to rewrite the functions or properties for every single new object, or in our case, every single new weapon. Instead, you can just write it out once and have the new weapon “inherit” those functions and properties, similarly to how Part and MeshPart inherit many of their properties and functions from the BasePart class.
So, whenever you have a lot of similar, yet still somewhat different objects with much overlapping functionality (such as vehicles, swords, guns), OOP can usually do the job pretty well. But that doesn’t mean you always have to use it.
But OOP is just one side of metatables. Say you want to make your own class such as a Vector3, or just want to be able to use operators with your table. Well in that case you absolutely can assign what the +, -, * and / (and many more) operators do with __add, __sub etc. For example:
local Vector4Meta = {}
local function NewVector4(x, y, z, w)
return setmetatable({X = x, Y = y, Z = z, W = w}, Vector4Meta)
end
function Vector4Meta:__add(value)
return NewVector4(self.X + value.X, self.Y + value.Y, self.Z + value.Z, self.W + value.W)
end
function Vector4Meta:__tostring()
return `\{ X = {self.X}, Y = {self.Y}, Z = {self.Z}, W = {self.W} \}`
end
local myVec4 = NewVector4(1, 2, 3, 4)
local otherVec4 = NewVector4(5, 6, 7, 8)
local sum = myVec4 + otherVec4
print(tostring(sum))
-- I have not tried any of this code but I hope it works