How do I immediately stop a function?

This is very hard to explain, so I’ll try to stick to the outline.

  1. What do you want to achieve?

What I am trying to achieve is in itself hard to explain. I am trying to detect if a player is looking in a direction (in this case a mirror).

chrome_2019-07-11_21-30-08

While the player is looking into a mirror, after a certain amount of time things should start to happen (flickering lights, etc.)

if the player looks away during this wait time (or during it) it will immediately end the process (the flickering lights) and run a function called normalize to set things back to normal immediately.

  1. What is the issue? Include screenshots/videos if possible!

I have made simple things happen, such as generating and destroying a brick as the status of “LookedAway” changes, what I cannot do is complex things such as functions, because I can find no way to “break” the process immediately.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I have tried using while loops while lookingAway ~= true do and render.Stepped, but none of these can get the result I need.

If anybody can get some insight on this it would help me greatly.

Code:

local lookingAtMirror
local lookedAway

local function checkStareStatus()
	if lookedAway == true then
		return true
	else
		return false
	end	
end

local function stareWait(inc)
	for i = 0,inc do
		wait(1)
		if checkStareStatus() == true then
			lookedAway = false
			return true
		end
	end
end

player:WaitForChild("Settings"):WaitForChild("lookingAtMirror").Changed:Connect(function()
	if player.Settings.lookingAtMirror.Value == true then
		print("Starting")
		if stareWait(5) ~= true then
			print("player has not looked away from mirror")
		end
	end
end)


renderStepped:Connect(function()
	if player:DistanceFromCharacter(Vector3.new(8.8, 6, 7.85)) <= 4 then -- Player is close to the mirror
		local facing = player.Character.HumanoidRootPart.CFrame.LookVector
		local vector = (Vector3.new(8.85, 3.75, 7.75) - player.Character.HumanoidRootPart.Position).unit
		local angle = math.acos(facing:Dot(vector))
		if angle <= 2 then -- Player is looking towards the mirror
			if player:WaitForChild("Settings"):WaitForChild("lookingAtMirror").Value ~= true then
				player:WaitForChild("Settings"):WaitForChild("lookingAtMirror").Value = true -- this prevents the function from happening twice if a player refocuses quickly
			end
		else
			player:WaitForChild("Settings"):WaitForChild("lookingAtMirror").Value = false -- looked away
		end
	else
		player:WaitForChild("Settings"):WaitForChild("lookingAtMirror").Value = false -- walked away
	end
end)

so to simplify it as much as I can, how can I “break” a function, as in immediately stopping it no matter where it is. I’m sorry if this is a bad question (like my previous ones), but I’m stumped.

You don’t want to put WaitForChild functions inside of a RenderStep function because RenderStep yields the client until the task is done. WaitForChild is only needs to be used once because it’s goal is to yield until the Child with name _____ exists.

Example:

local Player = game.Players.LocalPlayer;

Player:WaitForChild("Settings");
local LookingAtMirror = Player:WaitForChild("Settings"):WaitForChild("LookingAtMirror");
--^That is pointless because we already know that Settings exists at this point in time 

--Instead you would simply do 
Player.Settings:WaitForChild("LookingAtMirror");

I know thats not exactly what you did but it is what is occurring on every rendered frame, and this line

player:WaitForChild("Settings"):WaitForChild("lookingAtMirror").Changed:Connect(function()

Already guarantee’s that Settings and LookingAtMirror exists.
So a quick code fix would be to throw those references to the top of your script and change render stepped to heartbeat.

Now to solve your actual problem, what I would do is get rid of the stareWait() function and check the time in renderstepped


local STARE_TIME = 5;

HeartBeat:Connect(function()
	--Do your checks and what not
	if CheckAngles() and CheckDistance() then --Do your checks and what not
		LookingTime = tick();
	else 
		LookingTime = nil;
	end
	if LookingTime then
		if tick() - LookingTime > STARE_TIME then
			--Do your thing
		end
	end
end)

Sorry it took so long, but thanks. I used this after tweaking some things and it works perfectly!