Top-down 2D movement system support

I’m trying to have input from a client be sent to the server in order for all clients to be able to see it. The issue is that when I try to receive the info from the server, it doesn’t seem to work with while loops to check if those inputs are being pressed.

I’ve tried putting if statements inside the while loop but it’s still not stopping when the condition is not met: https://gyazo.com/bad1ca62e8141a7d294c0c0a744a4120

Server script inside server script service:

local remoteEvents = game:GetService("ReplicatedStorage").remoteEvents
remoteEvents.moveDirection.OnServerEvent:Connect(function(player,up,down,left,right)
	local dist = 1
	remoteEvents.moveDirection:FireAllClients(player,up,down,left,right,dist)
end)

Local script inside “gameUI” in StarterGUI:

local uis = game:GetService("UserInputService")
local remoteEvents = game:GetService("ReplicatedStorage").remoteEvents

local upKey = false
local downKey = false
local leftKey = false
local rightKey = false

uis.InputBegan:Connect(function(i)
	if i.KeyCode == Enum.KeyCode.W then
		upKey = true
	elseif i.KeyCode == Enum.KeyCode.S then
		downKey = true
	elseif i.KeyCode == Enum.KeyCode.A then
		leftKey = true
	elseif i.KeyCode == Enum.KeyCode.D then
		rightKey = true
	end
	remoteEvents.moveDirection:FireServer(upKey,downKey,leftKey,rightKey)
end)
uis.InputEnded:Connect(function(i)
	if i.KeyCode == Enum.KeyCode.W then
		upKey = false
	elseif i.KeyCode == Enum.KeyCode.S then
		downKey = false
	elseif i.KeyCode == Enum.KeyCode.A then
		leftKey = false
	elseif i.KeyCode == Enum.KeyCode.D then
		rightKey = false
	end
	remoteEvents.moveDirection:FireServer(upKey,downKey,leftKey,rightKey)
end)

remoteEvents.moveDirection.OnClientEvent:Connect(function(player,up,down,left,right,dist)
	while up do
		wait()
		print("Moving up...")
	end
end)

If I replace the while loop with an if statement like as follows:

remoteEvents.moveDirection.OnClientEvent:Connect(function(player,up,down,left,right,dist)
	if up then
		print("Moving up...")
	end
end)

then it seems to work fine with the text only printing when I begin pressing W.
https://gyazo.com/2d9c62fdbe397fee975c7f7e1ff56320

Maybe I’m doing this wrong? Maybe there’s an easier way that the information can be replicated to all clients? Really any help would be greatly appreciated!

The reason for the printing is because a new while loop “spawns” every time the event gets fired and the passed boolean “up” is true. It’s not going to stop the way you have your code structured right now.

remoteEvents.moveDirection.OnClientEvent:Connect(function(player,up,down,left,right,dist)
     while up do
    	 wait()
    	 print("Moving up...")
      end
  end)

The loop should only be updated when the input begins and ends though and the variable that’s being changed is the condition for the loop itself. Why won’t it stop?

Like I said, it’s creating a new while loop each time. If you send “up” as “true” the first time, it will create a new while loop and run forever even if you send “up” as “false” next time. If you fire the event again, but this time send “up” as “false”, it will not break the last while loop. It will only prevent it from running a new while loop.

How do I solve this issue? Just no RemoteEvent?

The first problem arises from the while X do preventing other fired events from being processed.

I cleaned up the code you provided a bit and made the data a little easier to process.

-- Client
local uis = game:GetService("UserInputService")
local remoteEvents = game:GetService("ReplicatedStorage").remoteEvents

-- Process these on the server, also removes the need for additional arguments
local keybinds = {
	[Enum.KeyCode.W] = "upKey",
	[Enum.KeyCode.S] = "downKey",
	[Enum.KeyCode.A] = "leftKey",
	[Enum.KeyCode.D] = "rightKey"
}

uis.InputBegan:Connect(function(data)
	local var = keybinds[data.KeyCode]
	if var then
		remoteEvents.moveDirection:FireServer(var)
	end
end)
-- Server
local remoteEvents = game:GetService("ReplicatedStorage").remoteEvents
remoteEvents.moveDirection.OnServerEvent:Connect(function(player, movementType)
	local dist = 1
	if movementType == "upKey" then

	elseif movementType == "downKey" then

	elseif movementType == "leftKey" then

	elseif movementType == "rightKey" then
		
	end
end)

What you are trying to do is quite messy and I’m not sure why you are doing it, but there is a solution. You can store keys of player id’s in a dictionary and the values are booleans that get toggled. Here’s an example.

local playerInputs = {}
remoteEvents.moveDirection.OnClientEvent:Connect(function(player,up,down,left,right,dist)
      playerInputs[player.UserId.."Up"] = up
      playerInputs[player.UserId.."Down"] = down
      playerInputs[player.UserId.."Left"] = left
      playerInputs[player.UserId.."Right"] = right
      while playerInputs[player.UserId.."Up"] do
    	   wait()
    	   print(player.Name .. " is moving up...")
       end
  end)

This is only an example and you’d probably need to manage this a little better with if statements so it doesn’t run while loops more than once.