I have this Localscript which handles the UI. When the player enters a zone, a textbox comes down. The first script invokes a RemoteFunction to check which type of information to display, but also the text, the color and the Endtime (if a cooldown should be displayed). When the player stands in the zone and the cooldown runs out, the the UIs are switched from the cooldown UI to the UI that basically tells the player he can press E to do whatever I want him to be able to do.
However, the issue is that the code breaks when the RemoteFunction is called on the client-side, but only when it is called through the “SwitchInterfaces” function. The “SwitchInterfaces” function calls the “InterfaceOut” function, that should pull the interface out, which calls the “CreateInterface” which calls the RemoteEvent and here it is where it breaks with the error “cannot resume dead coroutine”. I’ve removed the RemoteFunction and hardcoded the values and it worked, so for some reason the RemoteFunction breaks it. The serverside of the RemoveFunction also works perfectly fine and gives out the correct values if it wouldn’t brake the client-side code.
Note: The StartTime will be fetched from a DataStore in the future. For now I always change it to the current os.time() plus a few seconds to test
The error:
![]()
Client-side code:
-- VARIABLES
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local CollectionService = game:GetService("CollectionService")
local UserInputService = game:GetService("UserInputService")
local Function_Text = ReplicatedStorage:WaitForChild("Functions"):WaitForChild("Text")
local Function_InterfaceDisplayInfo = ReplicatedStorage:WaitForChild("Functions"):WaitForChild("InterfaceDisplayInfo")
local ZoneHandler = require(ReplicatedStorage.Modules.ZoneHandler)
local UI_Presets = ReplicatedStorage:WaitForChild("UI_Presets")
local StarterGui = Players.LocalPlayer.PlayerGui
local UI_Main = StarterGui:WaitForChild("UI_Main")
local CounterBackground = UI_Main.CounterBackground
local Connections = {}
local Threads = {}
local ZoneName = "UI_Zone"
local Number = 0
-- TWEEN_INFO
local Info_InfoBackground_Out = TweenInfo.new(0.2, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
local Info_InfoBackground_In = TweenInfo.new(0.2, Enum.EasingStyle.Back, Enum.EasingDirection.In)
-- HELPER FUNCTIONS
function SwitchInterfaces(Container)
local Tween_In = InterfaceIn(CounterBackground.InfoBackground)
Tween_In.Completed:Wait()
print("switching")
InterfaceOut(Container)
end
local function CreateCooldown(Type, NewInterface, EndTime)
local Thread
Thread = task.spawn(function()
local InterfaceText = NewInterface.TextLabel.Text
while true do
local SecondsBetween = os.difftime(EndTime, os.time())
local Seconds = SecondsBetween % 60
local Minutes = math.floor(SecondsBetween % (60 * 60) / 60)
local Hours = math.floor(SecondsBetween % (60 * 60 * 24) / (60 * 60))
local Days = math.floor(SecondsBetween % (60 * 60 * 24 * 30) / (60 * 60 * 24))
if Days >= 1 then
NewInterface.TextLabel.Text = InterfaceText.."\n("..Days.."d "..Hours.."h "..Minutes.."m "..Seconds.."s)"
elseif Hours >= 1 then
NewInterface.TextLabel.Text = InterfaceText.."\n("..Hours.."h "..Minutes.."m "..Seconds.."s)"
elseif Minutes >= 1 then
NewInterface.TextLabel.Text = InterfaceText.."\n("..Minutes.." m "..Seconds.."s)"
elseif Seconds >= 0 then
NewInterface.TextLabel.Text = InterfaceText.."\n("..Seconds.."s)"
end
if Days == 0 and Hours == 0 and Minutes == 0 and Seconds == 0 then
SwitchInterfaces(Type)
break
end
task.wait(0.5)
end
end)
table.insert(Threads, Thread)
end
local function CreateInterface(Container)
local Type = Container:GetAttribute("Type")
local InfoType, Text, Color, EndTime = Function_InterfaceDisplayInfo:InvokeServer(Type)
if InfoType == "OnCooldown" then
local NewInterface = UI_Presets.InfoBackground:Clone()
NewInterface.TextLabel.Text = Text
NewInterface.TextLabel.BackgroundColor3 = Color
NewInterface.Parent = CounterBackground
CreateCooldown(Container, NewInterface, EndTime)
elseif InfoType == "OffCooldown" then
print("off")
local NewInterface = UI_Presets.InfoBackground_Key:Clone()
NewInterface.Main.Text = Text
NewInterface.Main.BackgroundColor3 = Color
NewInterface.Name = "InfoBackground"
NewInterface.Parent = CounterBackground
elseif InfoType == "InfoOnly" then
local NewInterface = UI_Presets.InfoBackground:Clone()
NewInterface.TextLabel.Text = Text
NewInterface.TextLabel.BackgroundColor3 = Color
NewInterface.Parent = CounterBackground
end
end
-- MAIN FUNCTIONS
function InterfaceOut(Container)
CreateInterface(Container)
local TweenObject = CounterBackground:FindFirstChild("InfoBackground")
if CounterBackground:FindFirstChild("InfoBackground_Key") then
TweenObject = CounterBackground:FindFirstChild("InfoBackground_Key")
end
local Tween_Out = TweenService:Create(TweenObject, Info_InfoBackground_Out, {Position = UDim2.fromScale(0.5, 1)})
Tween_Out:Play()
print("tween played")
Tween_Out.Completed:Connect(function()
Tween_Out:Destroy()
end)
if TweenObject:GetChildren()[1]:IsA("TextButton") then
for _, Button in pairs(TweenObject:GetChildren()) do
local Connection_UI = Button.MouseButton1Up:Connect(function()
-- code to interaction
end)
table.insert(Connections, Connection_UI)
end
end
local Connection_Key = UserInputService.InputBegan:Connect(function(Input)
if Input.KeyCode == Enum.KeyCode.E then
-- code to interaction
end
end)
table.insert(Connections, Connection_Key)
end
function InterfaceIn(Object)
local Tween_In = TweenService:Create(Object, Info_InfoBackground_In, {Position = UDim2.fromScale(0.5, -0.01)})
Tween_In:Play()
for _, Connection in pairs(Connections) do
Connection:Disconnect()
end
Tween_In.Completed:Connect(function()
Tween_In:Destroy()
for _, Thread in pairs(Threads) do
task.cancel(Thread)
end
table.clear(Connections)
table.clear(Threads)
Object:Destroy()
end)
return Tween_In
end
for _, Container in pairs(CollectionService:GetTagged(ZoneName)) do
Zone = ZoneHandler.new(Container)
Zone.playerEntered:Connect(function(Player)
InterfaceOut(Container)
end)
Zone.playerExited:Connect(function(Player)
InterfaceIn(CounterBackground.InfoBackground)
end)
end
Server-side code:
-- VARIABLES
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local UI_Settings = {
["Types"] = {
["Red"] = {
Text_InCountdown = "You can't use the booster.",
Color_InCountdown = nil,
Text_OutCountdown = "Use the booster.",
Color_OutCountdown = Color3.fromRGB(135, 249, 255),
StartTime = 1717967562, -- Change it to
CooldownInfo = {
Seconds = 5,
Minutes = 0
}
}
}
}
local Function_Text = ReplicatedStorage:WaitForChild("Functions"):WaitForChild("Text")
local Function_InterfaceDisplayInfo = ReplicatedStorage:WaitForChild("Functions"):WaitForChild("InterfaceDisplayInfo")
-- FUNCTIONS
Function_InterfaceDisplayInfo.OnServerInvoke = function(Player, Type)
local Settings = UI_Settings.Types[Type]
if not UI_Settings.Types[Type] then
warn("UI-Settings for "..Type.." couldn't be found.")
return
end
local InfoType
local Text
local Color
local TotalSeconds = 0
local EndTime = nil
if Settings.CooldownInfo then
local StartTime = Settings.StartTime
for Info, Time in pairs(UI_Settings.Types[Type].CooldownInfo) do
if Info == "Seconds" then
TotalSeconds = TotalSeconds + Time
elseif Info == "Minutes" then
TotalSeconds = TotalSeconds + (Time * 60)
elseif Info == "Hours" then
TotalSeconds = TotalSeconds + (Time * 60 * 60)
elseif Info == "Days" then
TotalSeconds = TotalSeconds + (Time * 60 * 60 * 24)
elseif Info == "Months" then
TotalSeconds = TotalSeconds + (Time * 60 * 60 * 31)
elseif Info == "Years" then
TotalSeconds = TotalSeconds + (Time * 60 * 60 * 31 * 12)
end
end
if os.difftime(StartTime + TotalSeconds, os.time()) >= 1 then
Text = Settings.Text_InCountdown or "You forgot to add the text."
Color = Settings.Color_InCountdown or Color3.fromRGB(50, 131, 255)
InfoType = "OnCooldown"
EndTime = StartTime + TotalSeconds
else
Text = Settings.Text_OutCountdown or "You forgot to add the text."
Color = Settings.Color_OutCountdown or Color3.fromRGB(170, 0, 0)
InfoType = "OffCooldown"
end
else
Text = Settings.Text or "You forgot to add the text."
Color = Settings.Color or Color3.fromRGB(50, 131, 255)
InfoType = "InfoOnly"
end
-- here the correct values are always given, even if the client-side code still breaks
return InfoType, Text, Color, EndTime
end