Hello ,
The title might sound confusing but what I’m trying to do is quite simple. I have made a wrapper for a custom Vector3 for fun. I probably wont use it for anything unless I can make really useful stuff with it. But there is one slight issue that I have and that has to do with setting a Roblox instance’s position or size to the custom Vector3 type. (Or any property that uses Vector3) I’ve been using metatables and metamethods for the basic functions and now I just need a way to do that.
There is a simple way of doing it but I’d like to instead only give the custom Vector3 (It’s just a table connected to a metatable with some properties)
The simple way:
local VectorModule = require(script.VectorModule)
local part = workspace.part
local Vector = VectorModule.new(0, 5, 3) -- I make a Vector3
part.Position = Vector3.new(Vector.X, Vector.Y, Vector.Z)
What I want to achieve:
local VectorModule = require(script.VectorModule)
local part = workspace.part
local Vector = VectorModule.new(0, 5, 3)
part.Position = Vector
But obviously you can’t set a part’s position with a table. I was wondering if there was a metamethod to be able to convert this custom Vector table into an actual Vector3 behind the scenes but I couldn’t find this kind of metamethod anywhere on this website: Metatables
Is there no way of doing this? I’m also new to using metatables so feedback for the wrapper would be appreciated!
My custom vector wrapper:
local module = {}
-- Axis X = i, Axis Y = j, Axis Z = k
function module.calculateMagnitude(Vector) : number
return math.abs(math.sqrt(Vector.X ^ 2 + Vector.Y ^ 2 + Vector.Z ^ 2))
end
function module.calculateUnitVector(Vector)
return Vector / Vector.Magnitude
end
function module.calculateVector(Vector) : nil
Vector.Magnitude = module.calculateMagnitude(Vector)
if rawget(Vector, "Unit") ~= nil then
local Estimate = module.calculateUnitVector(Vector)
if not (Estimate == Vector.Unit) then
Vector.Unit = Estimate
end
end
end
function module.new(X : number, Y : number, Z : number)
local Vector = {}
setmetatable(Vector, module)
Vector.X, Vector.Y, Vector.Z = X, Y, Z
module.calculateVector(Vector)
return Vector
end
function module:setX(NewX : number)
self.X = NewX
module.calculateVector(self)
end
function module:setY(NewY : number)
self.Y = NewY
module.calculateVector(self)
end
function module:setZ(NewZ : number)
self.Z = NewZ
module.calculateVector(self)
end
function module:Dot(Vector) : number
return self.X * Vector.X + self.Y * Vector.Y + self.Z * Vector.Z
end
function module:Cross(Vector)
local DeterminantI = self.Y * Vector.Z - self.Z * Vector.Y
local DeterminantJ = self.X * Vector.Z - self.Z * Vector.X
local DeterminantK = self.X * Vector.Y - self.Y * Vector.X
local X, Y, Z = DeterminantI, DeterminantJ == -0 and 0 or -DeterminantJ, DeterminantK
local CrossVector = module.new(X, Y, Z)
return CrossVector
end
function module.zero() return module.new(0, 0, 0) end
function module.one() return module.new(1, 1, 1) end
function module.xAxis() return module.new(1, 0, 0) end
function module.yAxis() return module.new(0, 1, 0) end
function module.zAxis() return module.new(0, 0, 1) end
--<< Stuff >>--
function module.__index(t, Value)
if module[Value] == nil then
if Value == "Unit" then
t.Unit = module.calculateUnitVector(t)
return t.Unit
end
else
return module[Value]
end
end
--<< Operator Functions >>--
function module.__add(t, Value)
if type(Value) == "number" then
return module.new(t.X + Value, t.Y + Value, t.Z + Value)
elseif type(Value) == "table" or typeof(Value) == "Vector3" then
return module.new(t.X + Value.X, t.Y + Value.Y, t.Z + Value.Z)
end
error("Vectors can only be added by numbers or other vectors!")
end
function module.__sub(t, Value)
if type(Value) == "number" then
return module.new(t.X - Value, t.Y - Value, t.Z - Value)
elseif type(Value) == "table" or typeof(Value) == "Vector3" then
return module.new(t.X - Value.X, t.Y - Value.Y, t.Z - Value.Z)
end
error("Vectors can only be subtracted by numbers or other vectors!")
end
function module.__mul(t, Value)
if type(Value) == "number" then
return module.new(t.X * Value, t.Y * Value, t.Z * Value)
elseif type(Value) == "table" or typeof(Value) == "Vector3" then
return module.new(t.X * Value.X, t.Y * Value.Y, t.Z * Value.Z)
end
error("Vectors can only be multiplied by numbers or other vectors!")
end
function module.__div(t, Value)
if type(Value) == "number" then
return module.new(t.X / Value, t.Y / Value, t.Z / Value)
elseif type(Value) == "table" or typeof(Value) == "Vector3" then
return module.new(t.X / Value.X, t.Y / Value.Y, t.Z / Value.Z)
end
error("Vectors can only be divided by numbers or other vectors!")
end
function module.__eq(t, Value, x)
print(t, Value, x)
if type(Value) == "table" then
return (t.X == Value.X and t.Y == Value.Y and t.Z == Value.Z) and true or false
else
error(Value .. " is not the same datatype!")
end
end
--<< Printing >>--
function module.__tostring(self)
return table.concat({self.X, self.Y, self.Z}, ", ")
end
return module