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

I am trying to make a node system that finds the next closest part but cant make it work?

I am attempting to make a tram system that moves a tram along a table of nodes, which are parts on a track, using tween service. I can get the movement to the closest node working fine but then the node script recognizes that the closest node is the current one it is at causing the tram to stop forever. I know I need to make a if statement that detects if the current node is the closest one and then just skip it but I cant seem to figure out the implementation of it? If you can show me an updated script where it uses that technique I would greatly appreciate it. Thanks


local TS = game:GetService("TweenService")

local Engine = script.Parent:WaitForChild("Engine")

local Nodes = workspace:WaitForChild("Rails").RailNodes.Nodes

local NodeList = Nodes:GetChildren()
local closestNode = NodeList[1]

local lastClosestNode

function FindClosestNode()
	for i,node in pairs(NodeList) do
		if node.Name == "Node" then
			if (node.Position - Engine.Position).Magnitude < (closestNode.Position - Engine.Position).Magnitude then
				closestNode = node
			end
		end
	end
	return closestNode
end

function MoveForwardOneNode()
	
	local Tween = TS:Create(Engine, TweenInfo.new(3,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0),
	{CFrame = FindClosestNode().CFrame + Vector3.new(0,1.8,0)})
	
	Tween:Play()
	
	Tween.Completed:Wait()
	
	return true
end

repeat wait() until MoveForwardOneNode()

MoveForwardOneNode()

2 answers

You just have to check if the node is the same node as you said, and also you can just remove the node from the table after you "use" it once so it does not keep going back and forth, and then if you would like to reset it, you just call GetChildren() on the model again to fill the Nodes table

Here's the code:

llocal TS = game:GetService("TweenService")

local Engine = script.Parent
local Nodes = workspace:WaitForChild("Rails").RailNodes.Nodes

local NodeList = Nodes:GetChildren()
local closestNode = NodeList[1]

local lastClosestNode
local lowestNodeDistance = 1000 -- keep it a big number to begin with

function FindClosestNode()
	lowestNodeDistance = 1000
    for i,node in pairs(NodeList) do
        if node.Name == "Node" then
			local currentNodeDistance = (node.Position - Engine.Position).Magnitude 
           	if currentNodeDistance <= lowestNodeDistance  and node ~= lastClosestNode then
				closestNode = node
				lowestNodeDistance = currentNodeDistance
				currentNodeDistance = closestNode				
            end
        end
    end
    return closestNode
end

function MoveForwardOneNode()
	
	local closestNode = FindClosestNode()
	for i, v in pairs(NodeList) do -- I guess you don't want it to keep going back and forth 
		if v == closestNode then
			table.remove(NodeList, i)
		end
	end
   	local Tween = TS:Create(Engine, TweenInfo.new(3,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0),
    {CFrame = closestNode.CFrame + Vector3.new(0,1.8,0)})

    Tween:Play()

    Tween.Completed:Wait()
	lastClosestNode = closestNode
end

while true do 
	MoveForwardOneNode()
	wait(1)
end

There you have it, hope I helped, if you have further questions please let me know!

3 comments

0

This helped a lot thank you am wondering to why we need the lowestnodistance when it never changes at all in the script

0

wait so I just plugged the code in and the tram still only goes one node

0

Yeah I apologize, I didn't change the lowestNodeDistance back, which I was supposed to do every time we're trying to find the closestNode, I have fixed it

An easy way you can fix this is by remembering all the nodes that have already moved to. As I see it, there are two ways to do this; with an array, or with a table. In this case, let's do it using an array.

To start, let's set the value of lastClosestNode to an empty array.

local lastClosestNodes = {}

As well as making the variable plural, just for grammatical sake.

Now we need to add any node that we've moved to into the array. We can do this with the table.insert() method.

function FindClosestNode()
	  for i,node in pairs(NodeList) do
	      if node.Name == "Node" then
	          if (node.Position - Engine.Position).Magnitude < (closestNode.Position - Engine.Position).Magnitude then
	              closestNode = node
		      table.insert(lastClosestNodes, node)
	           end
	      end
	  end
	  return closestNode
end

As you can see, first we give the code the array we want to insert into, then what we want to insert.

After this, we just need to see if a node is in the array. Unfortunately, Lua doesn't have a simple way of doing this, so were gonna have to use a loop to find what were looking for

function FindClosestNode()
	  for i,node in pairs(NodeList) do
	      if node.Name == "Node" then
		  local nodeIsInArray = false -- Set this variable to true if we find the node
		  for i,v in pairs(lastClosestNodes) do -- Loop through every node in array
		  	if node == v then -- Check if the node is in the array
				nodeIsInArray = true -- If so, set the value to true
			end
		  end
	          if (node.Position - Engine.Position).Magnitude < (closestNode.Position - Engine.Position).Magnitude and nodeIsInArray == false then -- Check if the node is in array, if not, continue as normal
	              closestNode = node
		      table.insert(lastClosestNodes, node)
	           end
	      end
	  end
	  return closestNode
end

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