2

I am making a custom Vector3 class for a 3D engine I am making. I am kinda new to lua and not at the stage I should be making a 3D engine, but who cares. My Vector3 script looks like this.

#Vector3.lua
function Vector3(x,y,z) end

Vector3 = 
{
  __add = function(a,b)
    return Vector3(
      a.x + b.x,
      a.y + b.y,
      a.z + b.z
    )
  end
}
Vector3.__index = Vector3

function Vector3.new(x,y,z)
  local instance = 
  {
    x = x or 0,
    y = y or 0,
    z = z or 0
  }
  setmetatable(instance, Vector3)
  return instance
end

function Vector3:printX()
  return self.x
end

and my main like this:

#main.lua
require "Vector3"

vec1 = Vector3.new(1,2,3)
vec2 = Vector3.new(5,1,0)
vec3 = vec1 + vec2

print(vec3.x)

But it gives an error when I run it:

attempt to index global 'Vector3' (a function value)
stack traceback

I did this trying to have the __add function able to add two Vector3 classes. I know I am doing it incorrectly and I can't find a solution. How would I add the __add function to my script? This is the original Vector3.lua:

#Vector3.lua
Vector3 = {}
Vector3.__index = Vector3

function Vector3.new(x,y,z)
  local instance = 
  {
    x = x or 0,
    y = y or 0,
    z = z or 0
  }
  setmetatable(instance, Vector3)
  return instance
end

function Vector3:printX()
  return self.x
end
InSync
  • 4,851
  • 4
  • 8
  • 30
  • 2
    In `__add`, use `return Vector3.new(`. – lhf May 02 '23 at 13:50
  • @lhf Thank you. that worked. If you could explain why that works even though I define the Vector3.new() function after, that would be great. – TheJalfireKnight May 02 '23 at 13:54
  • The value will be retrieved at the time the `__add` is called after it gets modified. You could technically avoid it by prepending `local` to both `Vector3` declarations (table definition will shadow function definition in the later code), but don't do that. Check [cpml's vec3](https://github.com/excessive/cpml/blob/master/modules/vec3.lua) how to do it differently. – Aki May 02 '23 at 14:05

1 Answers1

3

The first definition of Vector3 that you have at the top of Vector3.lua is overwritten immediately:

function Vector3(x,y,z) end

Vector3 = 
{
-- ...
}

Global Vector3 is now a table and not a function. Later on in __add you try to call constructor via simplified Vector3():

__add = function(a, b)
  return Vector3(
--       ^^^^^^^^ here
    a.x + b.x,
    a.y + b.y,
    a.z + b.z
  )
end

Update that call to Vector3.new(...) or implement __call metamethod to construct the object (see 2.3 - Metatables and Metamethods). The error message suggests that there is another mix-up but if you clean up the code and implement one of the previous options it should be resolved.

Aki
  • 2,818
  • 1
  • 15
  • 23