Cannot Access "Self." Variables

Hey there! I’m pretty new to OOP and I was wondering how I can fix this code. Before I made the switch to “.self” variables, I was using variables inside each function which caused memory leaks. The main problem now is that I can access “self.” variables only from the “UpdateCam” method. Everywhere else, it returns an error. Also I feel like I shouldn’t be using so many self declarations in the “NewCam” function. Help is appreciated!

local UIS = game:GetService("UserInputService")

local camController = {}


camController.__index = camController

function lerp(a, b, t)
    return a + (b - a) * math.clamp(t, 0, 1)
end;


function camController.NewCam(plr)
    local self = setmetatable({},camController)

    self.Plr = plr
    self.Char = self.Plr.Character or self.Plr.CharacterAdded:Wait()
    self.Hum = self.Char:WaitForChild("Humanoid")
    self.HumData = {speed = self.Hum.WalkSpeed}
    self.HumRoot = self.Char:WaitForChild("HumanoidRootPart")
    self.Camera = game.Workspace.CurrentCamera
    self.CamData = {X = 0, Y = 0,frequency = 1.5,amplitude = 0.5,shakeIntensityX = .073, shakeIntensityY = 0.17, turn = 0, offset = 0}
    self.MouseDelta = nil
    self.tt = 0 

    return self
end

function  camController:MovingCam(HUM,data)
    self.Camera = workspace.CurrentCamera

    self.HumData.speed = HUM.WalkSpeed
    self.tt = tick() * self.HumData.speed / 3
    self.CamData.amplitude = 0.5
    self.CamData.frequency = 1.5

	self.CamData.X = -math.sin(self.tt * self.CamData.frequency) * self.CamData.amplitude  * data.shakeIntensityX
	self.CamData.Y = math.sin(self.tt * self.CamData.frequency * 2) * self.CamData.amplitude  * data.shakeIntensityY

    local offset = Vector3.new(self.CamData.X, self.CamData.Y, 0)
    offset = offset + Vector3.new(0, math.abs(offset.Y) * 0.01, 0)
    

    self.Camera.CFrame *= CFrame.new(offset)
end

function camController:IdleCam()
    self.Camera = workspace.CurrentCamera
    self.CamData.X = math.cos(tick() * 1) * 0.077
    self.CamData.Y = math.sin(tick() * 1) * 0.077

    self.CamData.offset = CFrame.new(Vector3.new(self.CamData.X, self.CamData.Y, 0), Vector3.new(self.CamData.X*0.95, self.CamData.Y*0.95, -10)) + self.Camera.CFrame.Position

	self.Camera.CFrame = self.Camera.CFrame:Lerp(self.CamData.offset * self.Camera.CFrame.Rotation, 0.2)
end

function camController:CamSway(dt)
    
    self.Camera = workspace.CurrentCamera
    self.MouseDelta = UIS:GetMouseDelta()
	
	self.CamData.turn = lerp(self.CamData.turn, math.clamp(self.MouseDelta.X, -4, 3), (4.7 * dt))
	self.Camera .CFrame = self.Camera .CFrame * CFrame.Angles(0, 0, math.rad(self.CamData.turn ))
end

function camController:UpdateCam(dt)
    camController:CamSway(dt)
    if math.abs(self.HumRoot.AssemblyLinearVelocity.X) > 5 or math.abs(self.HumRoot.AssemblyLinearVelocity.Z) > 5 then
        --Player is Moving
       camController:MovingCam(self.Hum,self.CamData)
    else
        --Player is Idle or has no movement
        camController:IdleCam()
    end
    
end


return camController

Change this to:

    local self = {}
    self.Plr = plr
    self.Char = self.Plr.Character or self.Plr.CharacterAdded:Wait()
    self.Hum = self.Char:WaitForChild("Humanoid")
    self.HumData = {speed = self.Hum.WalkSpeed}
    self.HumRoot = self.Char:WaitForChild("HumanoidRootPart")
    self.Camera = game.Workspace.CurrentCamera
    self.CamData = {X = 0, Y = 0,frequency = 1.5,amplitude = 0.5,shakeIntensityX = .073, shakeIntensityY = 0.17, turn = 0, offset = 0}
    self.MouseDelta = nil
    self.tt = 0 
    return setmetatable(self,camController)

Whats the difference? they both do the same thing.

It’s because you are setting the self variable as the setmetatable() before you can even put data in the table.

Instead of calling methods like this:

camController:MovingCam(self.Hum,self.CamData)

Call them like this:

self:MovingCam(self.Hum,self.CamData)

Also no need to pass self.Hum and self.CamData as params because you can simply access them from within the method itself via self.