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

How do I send information (from inside a for loop) using a RemoteEvent?

I'm making a script where when a player presses a button (E) on their keyboard they will start mining an ore. I also made a script that puts a TextLabel over the ore that is nearest to the player. It's kind of hard to explain, but here's the script with additional information inside:

local uis = game:GetService('UserInputService')
local hotkey = Enum.KeyCode.E

uis.InputBegan:Connect(function(key)
	if key.KeyCode == hotkey and script.Parent.Label.Visible == true then
		game.ReplicatedStorage.Events.Mine:FireServer(game.Players.LocalPlayer) --Point A
	end
end)

while true do
	script.Parent.Label.Visible = false
	for _, ore in pairs(workspace.Blocks:GetChildren()) do --I want to get the 'ore' and send it through the event that is fired at Point A (above)
		local mag = (ore.Position-game.Players.LocalPlayer.Character:WaitForChild('HumanoidRootPart').Position).magnitude
		if mag <= 10 then
			local D3ToD2 = workspace.CurrentCamera:WorldToScreenPoint(ore.Position)
			script.Parent.Label.Visible = true
			script.Parent.Label.Position = UDim2.new(0, D3ToD2.X, 0, D3ToD2.Y, 0)
			break
		end
	end
	wait()
end

Please help!

1 answer

✓ Accepted answer

Instead of firing the event inside the while loop, you can continuously fire the event inside the InputBegan event using a repeat until loop:

uis.InputBegan:Connect(function(key)
    if key.KeyCode == hotkey and script.Parent.Label.Visible == true then
		repeat
        game.ReplicatedStorage.Events.Mine:FireServer(game.Players.LocalPlayer)
		wait(1)
		until condition
    end
end)

You will have to have a condition that would stop the remote from sending, which in this case should tell you if the player has stopped mining.

From your current code, there is no variable that indicates whether the player is mining or not, so you have to create a variable, let's say IsMining, and set that to true when the player starts mining, and then set it to false when the player stops mining.

You can use InputEnded to detect when the player stops mining like so:

local IsMining = false
uis.InputBegan:Connect(function(key)
    if key.KeyCode == hotkey and script.Parent.Label.Visible == true then
		IsMining = true
		repeat
        	game.ReplicatedStorage.Events.Mine:FireServer(game.Players.LocalPlayer)
			wait(1)
		until not IsMining
    end
end)

uis.InputEnded:Connect(function(key)
	if key.KeyCode == hotkey then
		IsMining = false
	end
end)

Then you will have to be able to determine which ore the player is mining. For this, you can use a variable to store the current nearest ore, let's say, NearestOre. Set NearestOre to the nearest ore when the player gets near an ore

Here's what your code should look like:

local IsMining = false
local NearestOre
uis.InputBegan:Connect(function(key)
    if key.KeyCode == hotkey and NearestOre then -- script.Parent.Label.Visible == true has been replaced as now we can determine if the player can mine only if NearestOre contains a value
		IsMining = true
		repeat
        game.ReplicatedStorage.Events.Mine:FireServer(game.Players.LocalPlayer)
		wait(1)
		until not IsMining
    end
end)

uis.InputEnded:Connect(function(key)
	if key.KeyCode == hotkey then
		IsMining = false
	end
end)

while true do
    script.Parent.Label.Visible = false
    for _, ore in pairs(workspace.Blocks:GetChildren()) do
        local mag = (ore.Position-game.Players.LocalPlayer.Character:WaitForChild('HumanoidRootPart').Position).magnitude
        if mag <= 10 then
			NearestOre = ore -- set NearestOre to the nearest ore object
            local D3ToD2 = workspace.CurrentCamera:WorldToScreenPoint(ore.Position)
            script.Parent.Label.Visible = true
            script.Parent.Label.Position = UDim2.new(0, D3ToD2.X, 0, D3ToD2.Y, 0)
            break
        end
    end
    wait()
end

However, NearestOre will still contain the previous nearest ore even if you move away from any ores. What you want to do is set NearestOre to nil if no nearest ore is found.

Here's what it should look like:

while true do
	script.Parent.Label.Visible = false
	
	local oreFound = false -- create a variable that determines if an ore is found in the for loop
    for _, ore in pairs(workspace.Blocks:GetChildren()) do
        local mag = (ore.Position-game.Players.LocalPlayer.Character:WaitForChild('HumanoidRootPart').Position).magnitude
		if mag <= 10 then
			oreFound = true -- if an ore is found, set it to true
			NearestOre = ore

            local D3ToD2 = workspace.CurrentCamera:WorldToScreenPoint(ore.Position)
            script.Parent.Label.Visible = true
            script.Parent.Label.Position = UDim2.new(0, D3ToD2.X, 0, D3ToD2.Y, 0)
            break
        end
	end
	
	if not oreFound then -- if no ore is found, set NearestOre to nil
		NearestOre = nil
	end
    wait()
end

One more thing, when you fire a remote event to the server, you don't have to include the local player as that is already done by default, e.g.

-- client
remote:FireServer("hello")
-- server
remote.OnServerEvent:Connect(function(player, text)
	print(text) -- hello
end)

So to fire over the nearest ore to the server, just do game.ReplicatedStorage.Events.Mine:FireServer(NearestOre)

Here's what your final code should look like:

local IsMining = false
local NearestOre
uis.InputBegan:Connect(function(key)
    if key.KeyCode == hotkey and NearestOre then -- script.Parent.Label.Visible == true has been replaced as now we can determine if the player can mine only if NearestOre contains a value
		IsMining = true

		repeat
			game.ReplicatedStorage.Events.Mine:FireServer(NearestOre) -- fire over the nearest ore object to the server
			wait(1)
		until not IsMining
    end
end)

uis.InputEnded:Connect(function(key)
	if key.KeyCode == hotkey then
		IsMining = false
	end
end)

while true do
	script.Parent.Label.Visible = false
	
	local oreFound = false
    for _, ore in pairs(workspace.Blocks:GetChildren()) do
        local mag = (ore.Position-game.Players.LocalPlayer.Character:WaitForChild('HumanoidRootPart').Position).magnitude
		if mag <= 10 then
			oreFound = true
			NearestOre = ore

            local D3ToD2 = workspace.CurrentCamera:WorldToScreenPoint(ore.Position)
            script.Parent.Label.Visible = true
            script.Parent.Label.Position = UDim2.new(0, D3ToD2.X, 0, D3ToD2.Y, 0)
            break
        end
	end
	
	if not oreFound then
		NearestOre = nil
	end
	
    wait()
end

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