The while runs several times

The while loop runs several times, in theory it should break when the mouse moves away from the UI element, but this only works when the mouse leaves and waits a few seconds and only then goes back to the UI element, if it does this without waiting, the loop will start several times and the images will start blinking. What could be the reason?


Issue:


Code:

local MouseOnWindow = false

SkyFrame.SkyImage.MouseEnter:Connect(function()
	MouseOnWindow = true

	local InnerAngles = {}

	for Key, Angle in SkyboxAngles do
		if not table.find(InnerAngles, Element[Angle]) then
			InnerAngles[Key] = Element[Angle]
		end
	end

	local NextAngle = if #InnerAngles > 1 then if InnerAngles[1] == SkyFrame.SkyImage then 2 else 1 else 1

		while MouseOnWindow do
			SkyFrame.LastSkyImage.Image = SkyFrame.SkyImage.Image
			SkyFrame.LastSkyImage.ImageTransparency = 0

			SkyFrame.SkyImage.ImageTransparency = 1

			NextAngle = if NextAngle < #InnerAngles then NextAngle + 1 else 1

			SkyFrame.SkyImage.Image = InnerAngles[NextAngle]

			TweenService:Create(SkyFrame.LastSkyImage, TweenInfo.new(.15, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
				ImageTransparency = 1
			}):Play()

			TweenService:Create(SkyFrame.SkyImage, TweenInfo.new(.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
				ImageTransparency = 0
			}):Play()

			task.wait(1.15)
		end
	end)

SkyFrame.SkyImage.MouseLeave:Connect(function()
	MouseOnWindow = false

	if SkyFrame.SkyImage ~= Element.SkyboxFt then
		SkyFrame.LastSkyImage.Image = SkyFrame.SkyImage.Image
		SkyFrame.LastSkyImage.ImageTransparency = 0

		SkyFrame.SkyImage.ImageTransparency = 1
		SkyFrame.SkyImage.Image = Element.SkyboxFt

		TweenService:Create(SkyFrame.LastSkyImage, TweenInfo.new(.15, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
			ImageTransparency = 1
		}):Play()

		TweenService:Create(SkyFrame.SkyImage, TweenInfo.new(.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
			ImageTransparency = 0
		}):Play()
	end
end)
1 Like

just add a check if MouseOnWindow is false after the MouseEnter so everything inside it doesnt run multiple times

1 Like

Unfortunately this doesn’t work either

1 Like

It’s because you have a wait inside the loop:

while MouseOnWindow do
	SkyFrame.LastSkyImage.Image = SkyFrame.SkyImage.Image
	SkyFrame.LastSkyImage.ImageTransparency = 0

	SkyFrame.SkyImage.ImageTransparency = 1

	NextAngle = if NextAngle < #InnerAngles then NextAngle + 1 else 1

	SkyFrame.SkyImage.Image = InnerAngles[NextAngle]

	TweenService:Create(SkyFrame.LastSkyImage, TweenInfo.new(.15, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
		ImageTransparency = 1
	}):Play()

	TweenService:Create(SkyFrame.SkyImage, TweenInfo.new(.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
		ImageTransparency = 0
	}):Play()

	task.wait(1.15) -- Culprit
end

Basically, the conditional statement is checked again after the 1.15 seconds have passed. So it’s equivalent to:

if MouseOnWindow then
   -- Code
end

task.wait(1.15) -- Wait 1.15

if MouseOnWindow then
   -- Code
end

-- Keep repeating this process

The reason it repeats several times is because if you don’t wait the 1.15 seconds after the MouseLeave event, then the loop never ends because triggering the MouseEnter event will cause MouseOnWindow to still be equal to true. MouseOnWindow doesn’t have a unique value for each loop (it’s only true to get it to run). My suggestion would be to change the value from true to something like os.time() and replace:

while MouseOnWindow do
   -- Rest of code
end

with:

local current = os.time()
MouseOnWindow = current

while MouseOnWindow == current do
   -- Rest of code
end

This way, the loop would break if the current os.time() is not equal to the one that the loop checks. Hope this made sense and helps :slightly_smiling_face: . If you have any questions, let me know

1 Like

You could make it a BoolValue and utilize the .Changed event. So when it’s set to false, break the loop.

2 Likes

Thanks for the answer! It looks like while has been changed, because as far as I remember it didn’t work like that before. Previously, he constantly checked the condition, and then broke the loop without performing the following actions, but now apparently he was assigned the same logic as in

repeat
   task.wait()
until not MouseOnWindow

Loops have always worked like this. This is true for every programming language. A loop is just a block of code that is repeated x amount of times or until the conditional statement in a while loop is equal to false. The conditional statement does not get checked during every line inside the loop. Only the first. So an example would be like:

local ThisIsTrue = true

while (ThisIsTrue) do — Line 1 of loop, this is true so run block of code!
   print(“Segment 1”)
   print(“Segment 2”)
end — End of loop. Go back to line 1 of loop.

task.wait(1.15) yields the loop at the line it’s at for the (roughly) 1.15 seconds. So let’s say that you trigger the MouseLeaveevent but then trigger the MouseEnter event before the 1.15 second yield time has ended. The loop refers back to the first line and checks of the variable is true (which it is in this case) so it keeps running. You can even set the variable to false within the loop and it would still run as long as you trigger the MouseEnter event before the 1.15 second yield is complete:

while MouseOnWindow do
   MouseOnWindow = false
   task.delay(0.5, function()
      MouseOnWindow = true —This will cause the loop to still run because the variable is set back to true before the 1.15 second yield is completed
   end)
   task.wait(1.15)
end
1 Like

Thanks for the answer, thanks to your answer I came across a solution.

for Timeout = 0, 1.15, .1 do
	task.wait(.1)

	if not MouseOnWindow then
		break
	end
end

But I’m still curious what you meant by this:

In theory, it should create a unique conditional statement for every while loop created. This would allow the loop to break on it’s own whenever the variable no longer equals the unique value (os.time() in that example). Kinda like giving the loop it’s own unique key in a way. There’s plenty of other ways to do it. You can simply increment a value before the loop is created:

local current = 0

SkyFrame.SkyImage.MouseEnter:Connect(function()
   -- Code

   current += 1
   local key = current -- Store current's value in a separate variable
   MouseOnWindow = key -- Assign the variable to the value of "current"
   while MouseOnWindow == key do -- Checks if the variable is still equal to the value that was set before the loop was ran
      -- Code
   end
end)

So for example, if current was 0. MouseOnWindow would be set to 1 when MouseEnter is triggered and the loop will check if MouseOnWindow is equal to this number everytime it is ran. If you trigger the MouseEnter event again, MouseOnWindow’s value gets changed to 2. This causes the first loop to end, as the conditional statement is false:

while MouseOnWindow == key do -- This is false as key is equal to 1 and MouseOnWindow is equal to 2
   -- Code
end

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.