BindableEvent won't fire from ModuleScript?

Hey there, all!

So, I’ve made a countdown module and I want to check when the countdown ends, So I fire a BindableEvent. The bad thing is that it won’t fire at all. I’ve added prints to it, and they work, but the BindableEvent won’t fire. Thanks for any help!

Code
Module
--// Module Variables
local round = {}

--// ReplicatedStorage Variables
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Values = ReplicatedStorage:WaitForChild("Values")
local Status = Values:WaitForChild("Status")
local Timer = Values:WaitForChild("Timer")
local RoundInProgress = Values:WaitForChild("RoundInProgress")

--// Main
function round:Countdown(status : string, IsRoundInProgress : boolean, IsCountdownEnabled : boolean, Length : number)
	Status.Value = status
	RoundInProgress.Value = IsRoundInProgress
	
	if IsCountdownEnabled then
		Timer.Value = Length
		
		print("1")
		
		local function toMS(s)
			return ("%02i:%02i"):format(s / 60 % 60, s % 60)
		end
		
		for timer = Length, 0, -1 do
			Timer.Value = toMS(timer)
			task.wait(1)
		end
		
		print("2")
		
		local CountdownOver = Instance.new("BindableEvent")
		CountdownOver:Fire()
		
		print("3")
		
		return {CountdownOver.Event}
	end
	
	return
end

return round

--\\
Script
local _Round = require(game:GetService("ReplicatedStorage"):WaitForChild("_Round"))

local Intermission = _Round:Countdown("Intermission", false, true, 10)
local IntermissionCountdownEnded = Intermission[1]

IntermissionCountdownEnded:Connect(function()
	print("Ended!")
end)

Keep in mind that everything works except the BindableEvent firing.

2 Likes

I think you have to parent the bindable event first, not sure since I never used them before
EDIT: Ohh you have to connect it using

IntermissionCountdownEnded.Event:Connect(function()
   print("Ended!")
end)

You’re returning the event after the code finishes, so your event is being fired, just not at the right time. You can remedy this by creating a new thread inside of your countdown function, and then returning the signal:

function round:Countdown(status : string, IsRoundInProgress : boolean, IsCountdownEnabled : boolean, Length : number)
	Status.Value = status
	RoundInProgress.Value = IsRoundInProgress
	
	if IsCountdownEnabled then
        coroutine.wrap(function()
			Timer.Value = Length
		
			print("1")
		
			local function toMS(s)
				return ("%02i:%02i"):format(s / 60 % 60, s % 60)
			end
		
			for timer = Length, 0, -1 do
				Timer.Value = toMS(timer)
				task.wait(1)
			end
		
			print("2")
		
			local CountdownOver = Instance.new("BindableEvent")
			CountdownOver:Fire()
		
			print("3")
		end)()
		return {CountdownOver.Event}
    end
end
2 Likes

It’s not important to parent the BindableEvent, it works without being parented.

I’m confused here. You are returning CountdownOver.Event after the thread?

Yeah, it’s creating a separate thread which you can kinda think of as a separate script (although they aren’t the same, a separate thread just allows multiple instances of asynchronous code to run at one time) which runs at the same time as the timer is returned.

Thanks a lot! That fixed it nicely! Just had to make the Bindable Instance right after the IsCountdownEnabled ‘if’ statement!

1 Like