I have an IntValue inside of each player called “QueueSpot” when this value is changed this script down below will force the player to move to the correct queue spot.
It’s important that the player walks to every queue spot on the way to the final queue spot so it follows the path, but using MoveTo and MoveToFinished the player makes an fast stop by every queue spot. Which don’t look smooth.
I have tried solving this issue detecting the magnitude of the next spot it’s going to and if its close it should skip that queue spot and head to the next one instead which looked good. But doing that fix makes the MoveToFinished event not work properly as I am calling another MoveTo event when one is already called.
If anyone knows any tips or anything I am really glad to hear.
Here is a gyazo GIF - https://gyazo.com/ea1ef33e2e249ad157ebfd3f31198239
local QueueLine = workspace.QueueLine -- The model holding queue parts
local queueParts = {} -- Table to store queue parts
local playerLastSpots = {} -- Table to store each player's last QueueSpot
local movingPlayers = {} -- Table to track if players are currently moving
-- Fill the queueParts table with parts named '1', '2', ..., '50' (assuming 50 spots)
for i = 1, 50 do
table.insert(queueParts, QueueLine:FindFirstChild(tostring(i)))
end
local function moveToNextSpot(player, startSpot, endSpot, onFinalSpotReached)
local currentSpot = startSpot
-- Loop through the spots towards the target
while currentSpot ~= endSpot and movingPlayers[player.UserId] do
-- Determine the direction of movement
if currentSpot > endSpot then
currentSpot = currentSpot - 1
elseif currentSpot < endSpot then
currentSpot = currentSpot + 1
end
local targetPart = queueParts[currentSpot].Primary -- Get the primary part of the next spot
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
-- Move the player to the target part
humanoid:MoveTo(targetPart.Position)
-- Wait for MoveToFinished event instead of relying on magnitude check
humanoid.MoveToFinished:Wait()
-- If we reach the final spot, trigger the callback
if currentSpot == endSpot and movingPlayers[player.UserId] then
onFinalSpotReached()
end
end
end
-- This function will run when a player's QueueSpot value changes
local function onQueueSpotChanged(player, newQueueSpot)
-- Cancel the previous path if it exists
movingPlayers[player.UserId] = false
wait() -- Small delay to allow the cancellation to take effect
local oldQueueSpot = playerLastSpots[player.UserId] or newQueueSpot -- Get the previous spot or default to the current spot
playerLastSpots[player.UserId] = newQueueSpot -- Update the stored last spot
-- Start the new path and set movingPlayers[player.UserId] to true
movingPlayers[player.UserId] = true
moveToNextSpot(player, oldQueueSpot, newQueueSpot, function()
-- This function is called when the player reaches the final destination
print(player.Name .. " has reached their final QueueSpot: " .. newQueueSpot)
if player.Character then
-- Adjust player's rotation to match the target orientation
player.Character.HumanoidRootPart.CFrame = game.Workspace.QueueLine:FindFirstChild(newQueueSpot).Primary.CFrame
end
-- You can add any additional logic here when they reach the final spot
movingPlayers[player.UserId] = false -- Mark the player as no longer moving
end)
end
-- Continuously check for changes in QueueSpot for all players
while true do
for _, player in pairs(game.Players:GetPlayers()) do
local queueSpotValue = player:FindFirstChild("QueueSpot")
if queueSpotValue then
local newSpot = queueSpotValue.Value
if playerLastSpots[player.UserId] ~= newSpot then
onQueueSpotChanged(player, newSpot)
end
end
end
task.wait() -- Adjust the wait time to suit the game's performance needs
end
-- Optional: Clean up playerLastSpots and movingPlayers when a player leaves
game.Players.PlayerRemoving:Connect(function(player)
playerLastSpots[player.UserId] = nil
movingPlayers[player.UserId] = nil
end)