Reversing a for x = 1, y do loop

I want to reverse my for loop so my NPCs follow a path starting at 85 and then going down to their assigned number (min is 1).

	-- position is where the NPC should stop (85-1)
	for point = 1, position do
		humanoid:MoveTo(waypoints[point].Position)
		humanoid.MoveToFinished:Wait()
	end

Right now as you see above, the NPC starts at 1 so they just walk from their spawn to the other end.

I want the NPC to start at 85 and walk to all of the points until they end up where their position is set (e.g. stop at 14).

I hope I explained it well enough, any help is appreciated!

1 Like

Couldn’t you do this?

for point = 1, -position, -1 do
print(point)
	-- code
	end
2 Likes
-- position is where the NPC should stop (85-1)
	for point = 85, position, -1 do
		humanoid:MoveTo(waypoints[point].Position)
		humanoid.MoveToFinished:Wait()
	end
1 Like

This is the result, they all walk to point 16 and then back to 85 and then go to where they are supposed to be.

Yeah I updated the code, try this:

for point = 0, -position, -1 do
humanoid:MoveTo(waypoints[-point].Position)
		humanoid.MoveToFinished:Wait()
end

Ah, I see, nevermind I think @your_ojisan got it

They don’t move at all when I made it like that.

FYI: position is the NPCs set end point on the track

Is the waypoints array referring to an array of instances?

Got the stuff mixed up,
@DasKairo’s solution makes only one NPC go to point 1 while the rest don’t move.
The result from yours is the video in my first reply.

Yes, waypoints is a folder containing all the white points in the topic image

Simplify the waypoint instances to only be in each corner/directional change
Name the simplistic waypoints by number the instance of 1 being the beginning, in order to sort the :GetChildren() array by what should come first

for i,v in pairs(waypoints:GetChildren()) do task.wait()
	humanoid:MoveTo(v.Position)
	humanoid.MoveToFinished:Wait()
end

The problem is likely the array being casted is unsorted, the array does not know what is first and last

1 Like

Yeah, after testing @your_ojisan’s code using this:

for i = 1, #Parts do
	script.Parent.Humanoid:MoveTo(Parts[i].Position)
	script.Parent.Humanoid.MoveToFinished:Wait()
end


for i = #Parts, 1, -1 do
	script.Parent.Humanoid:MoveTo(Parts[i].Position)
	script.Parent.Humanoid.MoveToFinished:Wait()
end

Works as intended

Yeah I think the problem is that the array isn’t sorted (Idk how to sort it) but I want the NPCs to form a line along the track

Just want to note that the array has been local waypoints = AI_Points:GetChildren() the entire time.

LUA Sorts instances based on their name, you can also use table.sort() for noninstances or arrays containing strings numbers and other LUA-Types

Please provide more lines of code so we can understand what the script is supposed to do, apologies.

Preferably, the entire script

I think this should do it in reverse. Since you want it to start at position and end at 1, you want to switch position and 1, then put an increment of -1 afterwards.

-- position is where the NPC should stop (85-1)
	for point = position, 1, -1 do
		humanoid:MoveTo(waypoints[point].Position)
		humanoid.MoveToFinished:Wait()
	end

As for sorting positions, you may want to add intvalues to each waypoint, make each one unique in order from start to finish, then have the script sort waypoints by each point’s intvalue’s value.

No, I’m wanting it to end at the NPCs assigned end point which is what position is.

This is the entire script:

local ServerStorage, PhysicsService = game:GetService("ServerStorage"), game:GetService("PhysicsService")
local AI_Storage, Modules = ServerStorage:FindFirstChild("AI_Storage"), ServerStorage:FindFirstChild("Modules")
local AI_PathfindingPoints = AI_Storage:FindFirstChild("AI_PathfindingPoints")
local AI_Points = AI_PathfindingPoints:FindFirstChild("AI_Points")
local SpawnPoint, NPC_Dummy = AI_Storage:FindFirstChild("AI_SpawnPoint"), AI_Storage:FindFirstChild("NPC")

local module = {}

function module.Move(npc: Model, position: number)
	local humanoid = npc:FindFirstChild("Humanoid")
	
	for point = 1, position do
		humanoid:MoveTo(AI_Points[point].Position)
		humanoid.MoveToFinished:Wait()
	end
end

function module.Spawn(amount: number)
	local npc
	
	for i = 1, amount do
		task.wait(0.25)
		npc = NPC_Dummy:Clone()
		
		npc.AssignedPosition.Value = i
		npc.Parent = workspace.NPCs
		npc:FindFirstChild("HumanoidRootPart"):SetNetworkOwner(nil)
		
		for _, part in pairs(npc:GetChildren()) do
			if part:IsA("BasePart") then
				PhysicsService:SetPartCollisionGroup(part, "NPCs")
			end
		end
		
		coroutine.wrap(module.Move)(npc, npc.AssignedPosition.Value)
		
	end
end

return module
1 Like

In that case, you may want to specify both a start position and end position. Then, the for loop’s increment would be the sign of (end - start). That is, 1 if end > start, -1 is end < start, and 0 otherwise, though in that case the loop would end immediately given start and end would be the same.

In my mind; i’d assume you could just loop a function of spawning an NPC and moving their character along the waypoints seperately using task.spawn(), and label the waypoints by numbers in ascending order from Start-Finish, use the numbered waypoints as a means to define them as individuals, allowing you to define when they will stop

local function MoveCharacter(CustomEndAtPoint)
	return function ()
		local Character = script.NPC:Clone()
		Character.Parent = workspace
		
		local Humanoid = Character:WaitForChild("Humanoid")
		
		for i,v in pairs(workspace.waypoints:GetChildren()) do
			
			if tostring(CustomEndAtPoint) == v.Name then
				break
			end
			
			Humanoid:MoveTo(v.Position)
			Humanoid.MoveToFinished:Wait()
		end
	end
end

local function CloneNPCByAmount(Amount)
	local Index = 0
	repeat task.wait()
		task.spawn(MoveCharacter(14))
		Index = Index +1
	until Index == Amount
end
CloneNPCByAmount(15)

It probably would work something like this, however, for your usecase, you must create it yourself, this is just a concept for you

Heres some resources

task.spawn()
table.sort()

2 Likes