Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Why is my script not recognising this as a function?

Hello! So, I'm currently developing a system for my trains to move with, but I've ran into a sort of dead end.

Basically, whenever I call the :TweenCarriages() function, it just throws an error: attempt to call nil value.

I know it's not a problem with the script that's calling.

local TweenService = game:GetService("TweenService")

local TrainService = {}
TrainService.__index = TrainService

function TrainService.new(trainModel)
	assert(typeof(trainModel) == 'Instance')

	local self = setmetatable({},TrainService)

	self.TrainModel = trainModel
	self.CurrentNode = 1
	self.Carriages = {}
	self.Speed = 0
	
	
	return self
end

function TrainService:CreateNewCarriage(carriagePart)
	table.insert(self.Carriages, carriagePart)
	--print(typeof(self.Carriages[1]))
end

function TrainService:CalculateTime(distance, speed)		
	local Time = distance / speed
	
	return Time
end

 
function TrainService:TweenCarriage(tweenTime, nextNode, lastNode, carriageNumber)
	if not assert(typeof(nextNode) == "Instance" and nextNode:IsA("BasePart"), "nextNode must be a BasePart") then return end
	if not assert(typeof(lastNode) == "Instance" and lastNode:IsA("BasePart"), "lastNode must be a BasePart") then return end
	if not assert(tonumber(tweenTime), "tweenTime must be a Number") then return end
	
	local info = TweenInfo.new(
		tweenTime,
		Enum.EasingStyle.Linear,
		Enum.EasingDirection.InOut,
		0, -- RepeatCount (-1 = Infinite)
		false, -- Reverse tween after finishing
		0 -- DelayTime
	)
	
	local rot = nextNode.Rotation
	local rotY = nil
	
	local dotProduct = self.Carriages[carriageNumber].CFrame.LookVector:Dot(nextNode.CFrame.LookVector)
	
	if (dotProduct > 0.75) then
		rotY = nextNode.Rotation.Y
		-- Do something with dotY
	elseif (dotProduct < -0.75) then
		rotY = nextNode.Rotation.Y+180
		-- Do something else with rotY
	else
		rotY = nextNode.Rotation.Y
		warn("An issue has occurred.")
	end
		
	local position = {CFrame = CFrame.new(nextNode.Position)*CFrame.Angles(math.rad(rot.X),math.rad(rotY),math.rad(rot.Z))}
	
	
	local propertyTable = {
		CFrame = nextNode.CFrame
	}
	
	local tween = TweenService:Create(self.Carriages[carriageNumber],info,position)
	
	tween:Play()
	tween.Completed:Wait()
end

return TrainService

Any help would be appreciated!

1 answer

The solution is very easy. Just a typo XD Instead of :TweenCariages, you have the method as :TweenCariage()

Few other things to note. assert() is a standalone function that throws an error when the first parameter is not true, thus wrapping it with if-else (you do this in line 33 to 35) does literally nothing, so u can get rid of that. Secondly, when constructing the self, you should rather wrap all the components within the table rather than indexing them after for optimization (micro).

--Constructor Func Optimization
function TrainService.new(trainModel)
	return setmetatable({
		TrainModel = trainModel,
	   	CurrentNode = 1,
	    	Carriages = {},
	    	Speed = 0
	}, TrainService)
end

This discussion is preserved as it was. New answers, comments, and votes are closed.