Node based train kit

Hi,

I would like to achieve a node based train kit which updates its speed to match the value,

The issue I have currently is that when value updates, the speed stays the same and does not change throughout the course of the nodes

I have tried researching on the forum and other websites for quite some time but have not found the solution yet.

image

Current Script :

local rs = game:GetService("RunService")
local train = script.Parent
local curSpeed = train:WaitForChild("CurrentSpeed") -- Wait for the CurrentSpeed property to exist and retrieve it
local nodes = train.Parent.Parent.Nodes
local nodeReady = nodes.Parent.NodeReady
local loco = train.Locomotive
local front = loco.Front
local back = loco.Back
local base = loco.Base
local gap = (front.Position - back.Position).Magnitude
local loco_model = loco.Model
local remote = script.Parent.Parent.Parent.Parent.Parent.ServerScriptService.RemoteEvent
local startingNode = train.StartingNode

print("Started")
repeat wait() until nodeReady.Value 

function SetStartingNode()
	front.Current.Value = nodes:FindFirstChild("Node_" .. startingNode.Value)
	back.Current.Value = nodes:FindFirstChild("Node_" .. startingNode.Value)
end

function NextNode(target)
	local curNode = target.Current
	local nextNode = curNode.Value.NextNode.Value

	curNode.Value = nextNode
end

function Move(target, deltaTime)
	local curNode = target.Current.Value
	local nextNode = target.Current.Value.NextNode.Value

	if not nextNode then
		curSpeed.Value = 0
		return
	end

	local distanceTraveledOnSection = (curNode.Position - target.Position).Magnitude
	local sectionLength = (curNode.Position - nextNode.Position).Magnitude
	local newAlpha = ((distanceTraveledOnSection + curSpeed.Value * deltaTime)) / sectionLength

	target.CFrame = curNode.CFrame:Lerp(nextNode.CFrame, newAlpha)

	if newAlpha >= 1 then
		NextNode(target)
	end
end

function UpdateSpeed()
	while true do
		wait(1)
		curSpeed = train:WaitForChild("CurrentSpeed") -- Update the curSpeed value
	end
end

rs.Heartbeat:Connect(function(deltaTime)
	Move(front, deltaTime)
	Move(back, deltaTime)

	base.CFrame = CFrame.new(back.Position, front.Position) * CFrame.new(0, front.Size.Y/2 + base.Size.Y/2, -gap/2)
	loco_model:SetPrimaryPartCFrame(base.CFrame * CFrame.new(0, base.Size.Y/2 + loco_model.PrimaryPart.Size.Y/2, 0))
end)

SetStartingNode()

Please keep me updated as I am very confused about it.

1 Like

One thing to check is whether the Move function uses the correct value of curSpeed. You might want to update the Move function to include the new curSpeed value each time it’s called, like this:

function Move(target, deltaTime)
    local curNode = target.Current.Value
    local nextNode = target.Current.Value.NextNode.Value

    if not nextNode then
        curSpeed.Value = 0
        return
    end

    local distanceTraveledOnSection = (curNode.Position - target.Position).Magnitude
    local sectionLength = (curNode.Position - nextNode.Position).Magnitude
    local newAlpha = ((distanceTraveledOnSection + curSpeed.Value * deltaTime)) / sectionLength

    target.CFrame = curNode.CFrame:Lerp(nextNode.CFrame, newAlpha)

    if newAlpha >= 1 then
        NextNode(target)
    end
end

Double -check the code that sets the curSpeed variable to make sure it’s being called correctly and that there are no typos or errors. :+1:

That does work to some extent, I can only manage to make the train change speed by changing the value on the server side, any idea how a key bind would be able to change that value server side using a script?

Certainly! You could use a RemoteFunction to allow the client to send information to the server and change the speed value. So, it’ll be like:

– on the server side:local train = – set this to the train object you want to controllocal remoteFunction = Instance.new(“RemoteFunction”)remoteFunction.Name = “ChangeTrainSpeed”remoteFunction.OnServerInvoke = function(player, speed)train.curSpeed.Value = speedendremoteFunction.Parent = game.ReplicatedStorage

– on the client side:local remoteFunction = game.ReplicatedStorage:WaitForChild(“ChangeTrainSpeed”)local function onKeyDown(inputObject, gameProcessedEvent)if gameProcessedEvent then return endif inputObject.KeyCode == Enum.KeyCode.Space thenremoteFunction:InvokeServer(20) – change the number argument to the speed you wantendendgame:GetService(“UserInputService”).InputBegan:Connect(onKeyDown)

This sets up a RemoteFunction on the server that can be invoked by the client to change the train’s speed value. On the client side, you listen for a key press event and send the speed value through the remote function when the key is pressed.

It would probably be better to use a RemoteEvent rather than a RemoteFunction if feedback is not necessary. In this case, it is not necessary since you are just telling the server to change the speed of the train.

Thank you, it resolved the base of the problem. It certainly isn’t fully optimised in terms of performance for some reason but I’ll find a way to fix that.

With the structure, I currently set it to a Remote Event, but it works as good with a Remote Function.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.