Metatable objects return nil when trying to call a method

I want to make basic a player sprint mechanic using OOP.

The issue is that metatable objects return nil when i try to call a method called “playerSprint”

I’ve been trying to find some code mistakes. I was comparing my code with OOP code examples, but I still can’t find the thing that causes this error.

Did I do something wrong?
Ok here’s a code.

local movementScript = {}
movementScript.__index = movementScript

local UIS = game:GetService("UserInputService")
local ReplicatedS = game:GetService("ReplicatedStorage")

function movementScript.new(player: Player)
	local self = setmetatable({}, movementScript)
	self.Player = player
	self.Character = self.Player.Character
	self.Humanoid = self.Character.Humanoid
	self.boundKeys = require(ReplicatedS.Config.BoundKeys)
	return self
end

function movementScript:playerSprint(input: InputObject, isSprint: boolean)
	if table.find(self.boundKeys.Sprint, input.KeyCode) then
		if isSprint then
			self.Humanoid.WalkSpeed = self.Character:GetAttribute("sprintSpeed")
		else
			self.Humanoid.WalkSpeed = self.Character:GetAttribute("walkSpeed")
		end
	end
end

UIS.InputBegan:Connect(function(input)
	movementScript:playerSprint(input, true)
end)

UIS.InputEnded:Connect(function(input)
	movementScript:playerSprint(input, false)
end)

return movementScript

You call the method :playerSprint() but never actually constructed the class itself. You have to reference:

local movement = movementScript.new(Player)
movement:playerSprint(input, true)

Otherwise the method will not recognise the self variable and will return nil.

You made playerSprint a method of the instance, but you’re calling it on the class itself.

You have to construct an instance of the class using your .new constructor:

local ins = movementScript.new()
ins:playerSprint(....)

Also this script shows that this shouldn’t be a class at all, this is a great example of “not everything needs to be oop”.

You can just use:

local humanoid = --your humanoid
local char = --your character
local contextAction = game:GetService "ContextActionService"

contextAction:BindAction("Sprint", function(_, state, obj) 
    humanoid.WalkSpeed = state == Enum.UserInputState.Begin and char:GetAttribute "sprintSpeed" or char:GetAttribute "walkSpeed"
end, false, yourkeys)

Hope this helps.
Is there a reason why you’d want sprint to be oop?

This script is intended to be a movement script as it called, not just only sprint.
I just wanted to make basic sprint script as first.