UIGradient tween doesn't cancel properly

I have a script in which npc detects a player. When player is in the npc’s field of view, the animation of filling circle starts in billboardGui. In general everything works fine, but if the player hides during the circle animation it doesn’t cancel and continues to the end

local TweenService = game:GetService("TweenService")

local npcHead = workspace.SeeingNpc:WaitForChild("Head")
local character = game.Players.LocalPlayer.Character
local billboardGUI = npcHead.BillboardGui

local leftGradient = billboardGUI.progressBar.left.circle.UIGradient
local tween1 = TweenService:Create(
	leftGradient,
	TweenInfo.new(0.8, Enum.EasingStyle.Linear),
	{Rotation = 360})

local rightGradient = billboardGUI.progressBar.right.circle.UIGradient
local tween2 = TweenService:Create(
	rightGradient,
	TweenInfo.new(0.8, Enum.EasingStyle.Linear),
	{Rotation = -180})

local function startCounting()
	print("npc sees player")
	billboardGUI.Enabled = true
	
	tween1:Play()
	tween1.Completed:Wait() --I think the problem may be here, but I don't know what to do instead
	tween2:Play()
	tween2.Completed:Wait()
	
	leftGradient.Rotation = 180
	rightGradient.Rotation = -360
	billboardGUI.progressBar.Visible = false
	billboardGUI.detectedMark.Visible = true
end

function cancelDetection()
	print("npc DOESN'T see player")
	tween1:Cancel()
	tween2:Cancel()
	leftGradient.Rotation = 180
	rightGradient.Rotation = -360
	
	billboardGUI.Enabled = false
	billboardGUI.progressBar.Visible = true
	billboardGUI.detectedMark.Visible = false
end

while task.wait() do
	local distance = character.Head.Position - npcHead.Position
	local dot = (distance).Unit:Dot(npcHead.CFrame.LookVector)

	if dot > 0.5 then
		local rayParams = RaycastParams.new()
		rayParams.FilterType = Enum.RaycastFilterType.Exclude
		rayParams:AddToFilter({npcHead, character:GetChildren()})
		
		local raycast = workspace:Raycast(npcHead.Position, distance.Unit * distance.Magnitude, rayParams)
		if not raycast then
			startCounting()
		else
			cancelDetection()
		end
	else
		cancelDetection()
	end
end

Video example:

1 Like

Instead of using a tween, just lerp it inside your loop which offers much more control
you could technically do it with your tweens but it makes it much weirder

1 Like

try putting functions in task.spawn(), also to prevent functions play more than once add additional boolean which will display if function is playing or not (you need only for start function)

2 Likes

Yeah that’s the :Wait(). Your code is pausing the entire loop to wait for the tween to end (notice how “npc doesn’t see the player” only prints after the bar fully fills). You could instead either task.defer the function or use tween1.Completed:Once(function() … end) for the remaining code in startCounting

2 Likes

I’m not very familiar with lerp yet, and the other person’s answer also helped with my problem, but I will definitely give it a try thanks

1 Like

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