I started learning Metatables from a YouTube series on Lua this morning and I have run into a peculiar error while practicing Metatables. I made an advanced table previously and it had worked but it appears that the Metatable has caused it to break and I can't tell why. It prints out the coordinates and names correctly and then breaks when it attempts to connect to the move function. An explanation of what is going on and how it could be fixed would be greatly appreciated.
Error:
Workspace.Script:60: attempt to call field 'move' (a nil value)
Player = { x = 0, y = 0, z = 0, name = "", mt = {}, new = function() local p = {} setmetatable(p, Player.mt) return p end, move = function(p, x, y, z) p.x = p.x + x p.y = p.y + y p.z = p.z + z end } Player.mt.__add = function(p1, p2) local p = Player.new() p.x = p1.x + p2.x p.y = p1.y + p2.y p.z = p1.z + p2.z return p end Player.mt.__sub = function(p1, p2) local p = Player.new() p.x = p1.x - p2.x p.y = p1.y - p2.y p.z = p1.z - p2.z return p end Player.mt.__eq = function(p1, p2) return p1.x == p2.x and p1.y == p2.y and p1.z == p2.z end Player.mt.__tostring = function(p) return "("..p.x..", "..p.y..", "..p.z..")" end p1 = Player.new() p2 = Player.new() p1.x = 20 p1.y = 10 p1.z = 0 p1.name = "Player1" p2.x = 40 p2.y = 80 p2.z = 120 p2.name = "Player2" print(tostring(p1), p1.name) print(tostring(p2), p2.name) p1.move(p1, 50, -40, 60) p2.move(p2, 30, 10, -10) print(p1.x, p1.y, p1.z) print(p2.x, p2.y, p2.z) p3 = p1 + p2 p4 = p2 - p1 print(p3) print(p4) print(p3 == p4)
Your problem is that your function new
, returns a newly created table instead of the original, Player table, in which move
is located. Therefore, move
does not exist in the table returned by new. You can easily fix that without changing much of your code by doing the following.
You could use the __index
metamethod to refer back to the prototype
table Player. The event itself fires when table[key] is indexed. You would then configure it to return the function move
.
Player.mt.__index = function (_, key) return Player[key] end
The first argument represents the table being indexed, which we do not care for, and the following argument is the indexed key.