How should I go about this?

		for i, player in pairs(game.ServerStorage.playersInRound:GetChildren()) do
			
			character = game.Players:FindFirstChild(player.Name).Character
			character.Humanoid:MoveTo((gameElevator.elevatorFloor.Position + Vector3.new(0, 0, 30)) + Vector3.new(math.random(-5, 5), 5, math.random(-5, 5)))
			
			--separately (in a coroutine) enable player movement after the movement is completed
			coroutine.wrap(function()
				character.Humanoid.MoveToFinished:Wait()
				game.ReplicatedStorage.controlsRemoteEvents.enableControls:FireClient(game.Players:FindFirstChild(player.Name))
			end)()
			
		end
		
		
		--solidify elevator hitbox
		gameElevator.elevatorHitbox.CanCollide = true

Essentially what’s happening is players on an elevator have their controls disabled, I move them all off the elevator at the same time, then solidify a hitbox so that the players cannot get back on the elevator (their movement is enabled again shortly after)
The thing is, I don’t want the for loop to wait on each player’s movement to complete before the next one can start. So, I used a coroutine.
However, when doing this, I found that because of the coroutine, when the last player is up, the loop ends because the coroutine is running separately and the rest of the script runs, meaning the hitbox is solidified when the last player is in it, glitching them through the floor.

My ideas for solutions:
-Add a wait (I don’t like this solution much, as it could be inconsistent)
-Instead of immediately starting the tween, do constant checks for players in a region3, and if there are no players, solidify hitbox and move on (fairly certain this will work, but I’d prefer something simpler, if possible (if not then I guess I can just use this))

âś“ Solution


By the way, you structured the code it will not wait till all players are done. So you can use a different technique but using the same code:

By giving it the max count of players and then counting each time the player gets their controls back it will solidify the hitbox once the Finished amount equals the Max count.

local Max = game.ServerStrorage.playersInRound:GetChildren()
local Finished = 0

for i, player in pairs(game.ServerStorage.playersInRound:GetChildren()) do

	character = game.Players:FindFirstChild(player.Name).Character
	character.Humanoid:MoveTo((gameElevator.elevatorFloor.Position + Vector3.new(0, 0, 30)) + Vector3.new(math.random(-5, 5), 5, math.random(-5, 5)))

	--separately (in a coroutine) enable player movement after the movement is completed
	coroutine.wrap(function()
		character.Humanoid.MoveToFinished:Wait()
		game.ReplicatedStorage.controlsRemoteEvents.enableControls:FireClient(game.Players:FindFirstChild(player.Name))
		Finished += 1
	end)()

end


--solidify elevator hitbox


repeat 
	wait()
until Finished == #Max

gameElevator.elevatorHitbox.CanCollide = true

and if a player were to leave in the middle of it?

Switch the Max into the repeat loop so if a player leaves it will find the new limit.

repeat 
	wait()
	Max = game.ServerStrorage.playersInRound:GetChildren()
until Finished == #Max

Try this:

local currentHumanoid = nil

for i, player in ipairs(game.ServerStorage.playersInRound:GetChildren()) do
	character = player.Character
	character.Humanoid:MoveTo((gameElevator.elevatorFloor.Position + Vector3.new(0, 0, 30)) + Vector3.new(math.random(-5, 5), 5, math.random(-5, 5)))

	--separately (in a coroutine) enable player movement after the movement is completed
	task.spawn(function()
		currentHumanoid = character.Humanoid
		character.Humanoid.MoveToFinished:Wait()
		game.ReplicatedStorage.controlsRemoteEvents.enableControls:FireClient(game.Players:FindFirstChild(player.Name))
	end)
end

if currentHumanoid.WalkToPoint then
	currentHumanoid.MoveToFinished:Wait()
end

--solidify elevator hitbox
gameElevator.elevatorHitbox.CanCollide = true

You shouldn’t be using repeat loops for this, it’s much more performant if you just check if the last player is still moving.

I constantly ask this and somehow never figure out the answer
What’s the difference between ipairs and pairs? How is it useful here?

ipairs is for indexing through arrays such as these;

local array = {"dog", "cat", "monkey"}

pairs is for indexing through dictionaries like these;

local dictionary = {Dog = "cool boi", Cat = "cool cat", Monkey = "among us"}

You can use pairs for arrays too but I believe you get better performance if you use ipairs for arrays.

1 Like

ipairs being index-value pairs, right? so when using ipairs for an array its easier because its set up to be index value pairs already, contrary to a dictionary, where its key-value pairs?

Yes, exactly. To be honest though, it isn’t too much of a difference, so you shouldn’t worry about using the correct ones all the time (unless you want very specific micro-optimizations).