Making a wait that can be cancelled

Im trying to make a damage display gui, and im trying to make it so it doesnt stack labels and instead adds to the label, but i need to cancel the wait command to delete the current label, how do i cancel the wait?

local TweenService = game:GetService("TweenService")
local event = script.Event

local function displayDamage(damage)
	if not script.Parent:FindFirstChild("Label") then
		local template = script.Label
		local label = template:Clone()
		label.Parent = script.Parent
		label.Text = damage
		
		wait(3) -- i want to cancel this
		
		label:Destroy()
	else
		-- this is when i want to cancel it
	end
end
event.OnClientEvent:Connect(function(damage)
	displayDamage(damage)
end)
1 Like

Can’t you just destroy the previous label when a new one tries to load in?

5 Likes

I would review the approach to this, if you are wanting to show damage, you should have a UIList that will have many labels all at once so that they can stack and then disappear nicely using tweenService. However if you wish to do it this method what you can do is something like adding the label to DebrisService or use a delay This will make it so that you no longer have to have the script yield until it finishes.

local TweenService = game:GetService("TweenService")
local event = script.Event

local function displayDamage(damage)
	if not script.Parent:FindFirstChild("Label") then
		local template = script.Label
		local label = template:Clone()
		label.Parent = script.Parent
		label.Text = damage
		
		delay(3,function()
		    label:Destroy()
        end)
	else
		-- this is when i want to cancel it
	end
end
event.OnClientEvent:Connect(function(damage)
	displayDamage(damage)
end)
1 Like

add a conditional bool like i did below and put your wait in a while loop. when you want the wait to end, set the bool to true:

local TweenService = game:GetService("TweenService")
local event = script.Event
local condition = false

local function displayDamage(damage)
	if not script.Parent:FindFirstChild("Label") then
		local template = script.Label
		local label = template:Clone()
		label.Parent = script.Parent
		label.Text = damage
		while  not condition then -- will break once the condition becomes true.
		wait(1) -- i want to cancel this
                end

		
		label:Destroy()
	else
		-- this is when i want to cancel it
	end
end
event.OnClientEvent:Connect(function(damage)
	displayDamage(damage)
end)
2 Likes

Make it a thread:

local thread = task.spawn(displayDamage, damage)

--when you wish to terminate it:
task.cancel(thread)
2 Likes

you dont seem to understand, im trying to make it so when the player does damage while the existing label is there it instead adds to the current label and restarts the 3 seconds

Can you show the explorer hierarchy please?

just use httpservice:generateguid and update the id each time the ui shows up then do task.delay(3, function() and if the id still equals to the old id then destroy it

local UniqueId = HttpService:GenerateGUID(false);

UIElement:SetAttribute("UniqueId", UniqueId);
  
task.delay(3, function()
  
  if UIElement:GetAttribute("UniqueId") == UniqueId then
        UIElement:Destroy();
  end
end)
2 Likes

If that’s the case, then you can just use a status that you can use to tell if you need to remake the label or not, like so:

local TweenService = game:GetService("TweenService")
local event = script.Event
local reactivated = false

local function newLabel(dmg) 
       local template = script.Label
       local label = template:Clone()
       label.Parent = script.Parent
       label.Text = dmg
       return label
end


local function displayDamage(damage)
	if not script.Parent:FindFirstChild("Label") then
		local label = newLabel(damage)
        task.wait(3)
        if reactivated == false then 
            label:Destroy()
        end
	else
        reactivated = true
        local prevLabel  = script.Parent.Label
        local prevDamage = tonumber(script.Parent.Label.Text)
        prevLabel:Destroy()
	    local label = newLabel(damage + prevDamage)
        reactivated = false
        task.wait(3)
        if reactivated == false then
            label:Destroy()
        end
    end
end

event.OnClientEvent:Connect(function(damage)
	displayDamage(damage)
end)
1 Like
local cancel = false
local function displayDamage(damage)
	if not script.Parent:FindFirstChild("Label") then
		local template = script.Label
		local label = template:Clone()
		label.Parent = script.Parent
		label.Text = damage
		
		local start = tick()
		repeat task.wait() until cancel or tick() - start >= 3

		if not cancel then -- not sure if you want it not to delete when canceled
			label:Destroy()
		end

		cancel = false
	else
		cancel = true
	end
end