I'm working on a script that displays a "hold e" gui when the player gets close enough to the nearest designated object. When the player is within range, if they press and hold E an animation in the gui plays. After 3 seconds if the player lets go of E, an event is fired that destroys the object.

Here's my problem: after being close enough to the object and begun to hold E, if the player continues to hold e and walks away from the object they can come back to it or a different object and as long as they've held E for 3 seconds the animation will still play and the event will still fire when they let go of E.

I solved half of this problem by telling the script to set the currenttime/tick to nil if the player is not within range, BUT if I also tell the animation to cancel, then the script only works with one of my designated objects and will not work with any others until that object is destroyed.

--> How do make my holding-E tween animation cancel when the player is out of range, without breaking my script? <--

The problem spot is located towards the bottom function of the script:

local inputservice = game:GetService("UserInputService")
local TS = game:GetService("TweenService")
local TI = TweenInfo.new(3,Enum.EasingStyle.Linear, Enum.EasingDirection.Out,0,false,0)
local createAnim = TS:Create(script.Parent.Frame.ProgBar, TI, {Size = UDim2.new(1.1, 0, 0.339, 0)})

wait(2)

inputservice.InputBegan:Connect(function(input) --starts the animation when within range
	if input.KeyCode == Enum.KeyCode.E then
			for _,frontdoor in pairs(workspace.Destroyables:GetChildren()) do
				local Door = frontdoor:FindFirstChild("Destroyer")
					if Door ~= nil then
						local Mag = (Door.Center.Position-game.Players.LocalPlayer.Character.HumanoidRootPart.Position).magnitude
				if Mag <= Door.Range.Value then
					createAnim:Play()
					currenttime = tick()
							break
						end
					end
				end
	end
end)

inputservice.InputEnded:connect(function(i,g) -- stops the animation and fires event if within range
	if i.UserInputType == Enum.UserInputType.Keyboard then
		if i.KeyCode == Enum.KeyCode.E then
			for _,frontdoor in pairs(workspace.Destroyables:GetChildren()) do
				local Door = frontdoor:FindFirstChild("Destroyer")
					if Door ~= nil then
						local Mag = (Door.Center.Position-game.Players.LocalPlayer.Character.HumanoidRootPart.Position).magnitude
						if Mag <= Door.Range.Value then
						if currenttime ~= nil and (tick()-currenttime) >= 3 then
							Door.Event:FireServer()
							createAnim:Cancel()
							script.Parent.Frame.ProgBar.Size = UDim2.new(0, 0, 0.339, 0)
							currenttime = nil
						else
							createAnim:Cancel()
							script.Parent.Frame.ProgBar.Size = UDim2.new(0, 0, 0.339, 0)
							currenttime = nil
						end
						break
					end
				end
			end
		end
	end
end)

while true do -- makes the Gui visible when the nearest designated object is in range
	script.Parent.Frame.Visible = false
	for v, frontdoor in pairs(workspace.Destroyables:GetChildren()) do
		local Door = frontdoor:FindFirstChild("Destroyer")
			if Door ~= nil then
			local Mag = (Door.Center.Position-game.Players.LocalPlayer.Character.HumanoidRootPart.Position).magnitude
			if Mag <= Door.Range.Value then
				local D3ToD2 = workspace.CurrentCamera:WorldToScreenPoint(Door.Center.Position)
				script.Parent.Frame.Visible = true
				script.Parent.Frame.Position = UDim2.new(0,D3ToD2.X,0,D3ToD2.Y,0)
				break
			else
				currenttime = nil -- this one works fine to stop the time part
				createAnim:Cancel()	-- including this command ruins the script and causes it to only work one object (but the gui is still visible when I get close enough to another one)
			end
		end
	end
	wait()
end