Metatable returns nil

EDITED 28/05/2021

Seven months later and I’m back with this problem again. What I did in the reply above was very messy, so I thought hey, why not bump this topic instead of creating a new one.

Today I tried making a spring module but the metatables didn’t work. Again. So I just straight up took the code from one of EgoMoose’s tutorials and it didn’t work aswell. I literally no idea what I’m doing wrong.

Error: ReplicatedStorage.Modules.Shared.Spring:17: attempt to perform arithmetic (sub) on nil - Spring:17 - I checked and self is only a table of the functions in the module.

ModuleScript (Spring)

local spring = {}
spring.__index = spring

function spring.new(position, velocity, target)
    local self = setmetatable({}, spring)
    self.position = position
    self.velocity = velocity
    self.target = target
    self.k = 1
    self.friction = 1

    return self
end

function spring:update()
    local d = (self.target - self.position)
    local f = d * self.k
    self.velocity = (self.velocity * (1 - self.friction)) + f
    self.position += self.velocity
end

return spring

ServerScript

local springModule = require(game:GetService("ReplicatedStorage").Modules.Shared.Spring)
local spring = springModule.new(workspace.Part1.Position, 1, workspace.Part2.Position)

game:GetService("RunService").Stepped:Connect(function()
    spring.target = workspace.Part2.Position
    springModule:update()
    workspace.Part1.Position = spring.position
end)
Old Topic

I am trying to make self a variable across the entire ModuleScript, but (see last function) self is nil.

local handler = {}
local mt = {__index = handler}

function handler.new() -- fired when the player enters (from a LocalScript)
    local self = {}
    self.aiming = false

    return setmetatable(self, mt)
end

function handler:aim()
    print(self.aiming) --> prints nil
end

I already tried asking this on Discord and Reddit, but got no reply, and also tried looking on the Developer Hub and even copying the examples one by one and it still didn’t work

Disclaimer: I have no idea if I am actually making sense or if that’s even how metatables work, but I’ve seen some open source code that does exactly what I am doing and works. Please excuse me if this is a stupid question.

This works:

local HandlerClass = {}
local HandlerInstanceMT = {
    __index = HandlerClass
}

function HandlerClass.New()
    local self = {}
    self.aiming = false
    return setmetatable(self, HandlerInstanceMT)
end

function HandlerClass:Aim()
    print(self.aiming)
end

local handler = HandlerClass.New()
handler:Aim() --prints "false"

I don’t know why yours doesn’t, can’t spot any differences. Are you calling the methods properly? Try printing the object you get back from Class.New, and also print “self” in the :aim method. They should be the same, if they’re not then that explains why self.aiming might be nil.

Yours works, but not in my context. This is so weird.

Does it matter if I have more than one function? (For example Handler:Aim() and Handler:Fire())

No, that shouldn’t matter. Can you upload the place file?

[REDACTED_broken]
(kind of messy, don’t mind my weird notes)

ModuleScript (inside ReplicatedStorage.Modules, named fps)
LocalScript (inside StarterGui, named Control)

I wanted to try and step through your code, inspecting variables at different points in time, but since your code isn’t in a working state I can’t do that.

I’m stumped :confused: I thought maybe you were overwriting the .aiming member to be nil, but doesn’t seem like it.

Couldnt you just do:

local Handler = {}
Handler.__index = Handler

function Handler.new()
	local self = setmetatable({}, Handler)
	
	self.Aiming = false
	
	return self
end

function Handler:Aim()
	print(self.Aiming) 
end

return Handler

I am sorry, I gave you a broken version.
If you still have time, this one works; []

This one also does not work in my context. I am pretty sure I messed something up elsewhere, but I have no idea where.

Are you calling Handler:Aim() with the colon/method syntax? It won’t work if you call it with a dot. Handler.Aim()

I am calling Handler:Aim (with “:”) and Handler:New (with “.”).

I have no idea why, but I fixed it by setting up the metatable in handler.new and adding all of the variables in a different function (handler.setupTable).

Seven months later and I’m back with this problem again. What I did in the reply above was very messy, so I thought hey, why not bump this topic instead of creating a new one.

Today I tried making a spring module but the metatables didn’t work. Again. So I just straight up took the code from one of EgoMoose’s tutorials and it didn’t work aswell. I literally have no idea what I’m doing wrong.

Error: ReplicatedStorage.Modules.Shared.Spring:17: attempt to perform arithmetic (sub) on nil - Spring:17 - I checked and self is only a table of the functions in the module.

ModuleScript (Spring)

local spring = {}
spring.__index = spring

function spring.new(position, velocity, target)
    local self = setmetatable({}, spring)
    self.position = position
    self.velocity = velocity
    self.target = target
    self.k = 1
    self.friction = 1

    return self
end

function spring:update()
    local d = (self.target - self.position)
    local f = d * self.k
    self.velocity = (self.velocity * (1 - self.friction)) + f
    self.position += self.velocity
end

return spring

ServerScript

local springModule = require(game:GetService("ReplicatedStorage").Modules.Shared.Spring)
local spring = springModule.new(workspace.Part1.Position, 1, workspace.Part2.Position)

game:GetService("RunService").Stepped:Connect(function()
    spring.target = workspace.Part2.Position
    springModule:update()
    workspace.Part1.Position = spring.position
end)

You store the position, velocity and other values in the spring object (variable spring in the server script). This means that the values are not stored inside the spring class. They are stored inside the spring object, so instead of springModule:Update() you should have spring:Update(). The object inherits the :Update() method from the class.

2 Likes

I didn’t know that that’s how it works, thank you!