While True Do loop Not Detecting boolvalue.Value change

Hello!

In my script it detects when the player has touched a part. From then it changes the boolvalue to true. Further then, i made a while true do loop which detects if the boolvalue has been set to true. However, the boolvalue does not detect the boolvalue when it changed to true and doesn’t print ANY of the print statements in the script. Any Help?

Script

	local debounce = false
	local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local PartTouchValue = ReplicatedStorage.PartTouchValue
	PartTouchValue.Value = false
	
	while true do
		task.wait()
		if not debounce then 
			debounce = true
			
			local part = workspace.Build.TouchPart

			local function onTouch(hit)
			local character = hit.Parent
			local humanoid = character:FindFirstChild("Humanoid")
			if humanoid then
				print(character.Name .. " touched the part!")
				PartTouchValue.Value = true
				task.wait()
				debounce = false
			end
		end

			part.Touched:Connect(onTouch)
			
		end
		
	end
	
	while true do
		task.wait()
		if PartTouchValue.Value == true then
			print("Continued")
			break
		else 
			print("Part not touched")
		end
	end
1 Like

There are two major issues with your code.

  1. Its design creates a memory leak
  2. Its design is synchronous

Problem #1 is created by the duplication of the event handler onTouch. Your loop, at a rate of ~60 times a second, connects onTouch to part.Touched. This will bombard the event with duplicate event handlers, leading to an ever-increasing response to the event and memory usage. This is extremely bad. Your design isn’t justified as BasePart.Touched will invoke its connected event handlers each time a collision is made with that BasePart—there is no need connect a specific event handler more than once. You may be confused on how events work in Roblox, so I recommend learning more about them here.

Problem #2, the problem you’re experiencing, is created by a misunderstanding of control flow. A script is executed line-by-line, from left → right, top → bottom. Pretty much exactly how you read Western books. When it comes to while loops, the control structure modifies code flow to return to the top of the loop so long as the loop’s condition is met. Your first loop is ever-lasting, meaning it will continue to disrupt the downward flow of the script forever. This prevents your second loop from ever being reached, which is why you don’t see any activity from it. If you mean to run code when the part is touched, you need only include that code within the event handler:

local function onTouched(otherPart: BasePart)
    local character = otherPart.Parent

    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if not humanoid then
        return
    end

    print(character.Name .. "touched the part!")

    -- Do everything else.
end


part.Touched:Connect(onTouched)

To run code when something that was already touching your part stops touching it, use BasePart.TouchEnded. If your intention is to run code while a Model with a child Humanoid is in contact with the part, you will need a different design. Utilize the spatial query API:

local Players = game:GetService("Players")
local function getCharacters(): {Model}
    local characters = {} :: {Model}

    for _, player in Players:GetPlayers() do
        local character = player.Character
        if character then
            table.insert(characters, character)
        end
    end

    return characters
end
local Part = workspace.Part


while true do
    local overlapParams = OverlapParams.new()
    overlapParams.FilterDescendantsInstances = getCharacters()
    overlapParams.FilterType = Enum.RaycastFilterType.Include

    if #workspace:GetPartsInPart(Part, OVERLAP_PARAMS) > 0 do
        print("Characters are touching the part!")
    else
        print("No characters touching the part!")
    end

    task.wait()
end

Now, the above solution isn’t very ideal either. Unfortunately, the best way to approach this kind of problem requires a whole lot more work. You can use a module like ZonePlus, but that may be overkill for your needs. I have developed my own simplified version called PlayerTracker, but even this may not perfectly fit your situation. There are always more exact solutions, but we’d need to know what your ultimate goal is

3 Likes

hi
in this code it is better to use one while loop rather than 2 while loops

code:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PartTouchValue = ReplicatedStorage:WaitForChild("PartTouchValue")

local part = workspace.Build.TouchPart
PartTouchValue.Value = false

local function onTouch(hit)
    local character = hit.Parent
    local humanoid = character:FindFirstChild("Humanoid")

    if humanoid then
        print(character.Name .. " touched the part!")
        PartTouchValue.Value = true
    end
end
part.Touched:Connect(onTouch)

while true do
    task.wait(.5)
    if PartTouchValue.Value then
        print("Continued")
        break
    else 
        print("Part not touched")
    end
end
1 Like

What confuses me is why OP would want to break. Are they just waiting for the first player to touch the part?

Thank you for the Help!!!

What were you trying to achieve with that code?

The second while true do loop wasn’t printing any on the print messages. Furthermore the seconds loop didn’t detect if the boolvalue turned true. But now it is fixed from the comment by Mirbah.

That did not answer my question; I’m asking what your code was supposed to work towards