Repeat a loop while touching a part

I’m trying to add a stat to the player every second while the player is touching a specific part. I can’t seem to figure out this pretty simple problem. I tried using a tutorial on the devforum and customize it to fit my script but it just doesn’t work.

for _, area: Part in pairs(current_areas:GetChildren()) do
	local touching = false
	adding = 1 * stats[script.Parent.MultiplierName.Value].Value * area.Multiplier.Value
	
	area.Touched:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			touching=true	
		end
	end)

	area.TouchEnded:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			touching=false	
		end
	end)

	coroutine.wrap(function()
		while touching do
			task.wait(1)
			data_manager.ChangeStat(player, script.Parent.Name, adding, "Add")
		end
	end)()
end

Okay here’s 2 things I noticed:

  1. The touching variable is global, meaning that each player doesn’t have their own ‘touching’ variable.
  2. The while loop will stop immediately as touching is false to begin with.

Here’s a revised version to help you:

local Players = game:GetService("Players")

local isTouching = {}
local addingAmount = {}

Players.PlayerAdded:Connect(function(player)
	isTouching[player.UserId] = false
	addingAmount[player.UserId] = 0
end)

Players.PlayerRemoving:Connect(function(player)
	isTouching[player.UserId] = nil
	addingAmount[player.UserId] = nil
end)

for _, area: Part in pairs(current_areas:GetChildren()) do
	local adding = 1 * stats[script.Parent.MultiplierName.Value].Value * area.Multiplier.Value
	
	area.Touched:Connect(function(hit)
		local player = Players:GetPlayerFromCharacter(hit.Parent)
		if player then
			isTouching[player.UserId] = true
			addingAmount[player.UserId] = adding
		end
	end)

	area.TouchEnded:Connect(function(hit)
		local player = Players:GetPlayerFromCharacter(hit.Parent)
		if player then
			isTouching[player.UserId] = false	
			addingAmount[player.UserId] = 0
		end
	end)
end

task.spawn(function()
	while true do
		task.wait(1)
		for _, player in pairs(Players:GetPlayers()) do
			if isTouching[player.UserId] then
				data_manager.ChangeStat(player, script.Parent.Name, addingAmount[player.UserId] or 0, "Add")
			end
		end
	end
end)
1 Like
for _, area: Part in pairs(current_areas:GetChildren()) do
	local Player
	adding = 1 * stats[script.Parent.MultiplierName.Value].Value * area.Multiplier.Value

	area.Touched:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			Player = player
			area.TouchEnded:Once(function()
				Player = nil
			end)
		end
	end)
	
	local t = 0
	local ld = 1

	game:GetService("RunService").Heartbeat:Connect(function(dt)
		if Player then
			t += dt
			while t >= ld do
				t -= ld
				data_manager.ChangeStat(player, script.Parent.Name, adding, "Add")
			end
		end
	end)
end

and here’s my attempt

This doesnt seem to work for me. Also this is just a part of my script which is a client script

Could you share the entirety of the script or something? Maybe I’m missing something. Is it throwing an error?

I know its a bit messy, but this wont have to be reusable that much as i have only 3 tools.
No errors.
+

local player = game.Players.LocalPlayer
local char = player.Character
local humanoid = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")
local stats = player:WaitForChild("stats")

local replicated_storage = game:GetService("ReplicatedStorage")
local animations = replicated_storage:WaitForChild("Animations")
local data_manager = require(replicated_storage:WaitForChild("DataManager"))
local popup_service = require(replicated_storage.Packages:WaitForChild("PopupService2"))
local abbrev_module = require(replicated_storage.Packages:WaitForChild("AbbrevModule"))

local cooldown = replicated_storage.Settings.Cooldown.Value
local debounce = false

local train_areas = workspace:WaitForChild("TrainAreas")
local current_areas = train_areas:WaitForChild(script.Parent.Name)

local hold_track = humanoid:LoadAnimation(animations.Body_Toughness_Hold)
local click_track = humanoid:LoadAnimation(animations.Body_Toughness_Hold.Body_Toughness_Action)

hold_track.Priority = Enum.AnimationPriority.Action
click_track.Priority = Enum.AnimationPriority.Action

for _, area: Part in pairs(current_areas:GetChildren()) do
	local touching = false
	adding = 1 * stats[script.Parent.MultiplierName.Value].Value * area.Multiplier.Value

	area.Touched:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			touching=true	
		end
	end)

	area.TouchEnded:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			touching=false	
		end
	end)

	coroutine.wrap(function()
		while touching do
			task.wait(1)
			data_manager.ChangeStat(player, script.Parent.Name, adding, "Add")
		end
	end)()
end

local adding

local function on_activate()
	if debounce then return end
	debounce = true

	adding = 1 * stats[script.Parent.MultiplierName.Value].Value

	click_track:Play()
	data_manager.ChangeStat(player, script.Parent.Name, adding, "Add")
	task.spawn(function()
		popup_service.Create(script.Parent.Name, adding)
	end)

	task.wait(cooldown)
	debounce = false
end

for _, area: Part in pairs(current_areas:GetChildren()) do
	local touching = false
	adding = 1 * stats[script.Parent.MultiplierName.Value].Value * area.Multiplier.Value

	area.Touched:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			touching=true	
		end
	end)

	area.TouchEnded:Connect(function(hit)
		local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
		if player then
			touching=false	
		end
	end)

	coroutine.wrap(function()
		while touching do
			task.wait(1)
			data_manager.ChangeStat(player, "Body Toughness", adding, "Add")
		end
	end)()
end

script.Parent.Activated:Connect(on_activate)

script.Parent.Equipped:Connect(function()
	for _, track in pairs(humanoid:GetPlayingAnimationTracks()) do
		track:Stop()
	end

	hold_track:Play()
	humanoid.WalkSpeed = 0
	humanoid.JumpPower = 0
end)

script.Parent.Unequipped:Connect(function()
	hold_track:Stop()
	click_track:Stop()
	humanoid.WalkSpeed = 16
	humanoid.JumpPower = 50
end)

Ooh thank you! I suggest switching this to a server script because it will prevent exploiters from randomly changing their stats. Also any updates to the values will not appear on the server/for other clients. You would definetly have to split the code into a local script and server script.