the events never fire, even though debug prints inside handle_button print normally. The worst part is that the connections ARE created and connected, just not fired
What I already checked:
Buttons exist and are fully parented when the module function runs
When you use direct indexing for a screen gui found on the PlayerGui, it will most likely not exist yet, local or server. I know this from experience
Try replacing this line: local button = player.PlayerGui.MainUI.BottomBar.Container.Bar.Configuration
With this line; local button = player.PlayerGui:WaitForChild("MainUI").BottomBar.Container.Bar.Configuration
--ModuleScript in ReplicatedStorage.MyModule
local mod = {}
function mod.handle_button(button, actions)
if actions.click then
button.MouseButton1Click:Connect(function()
actions.click(button)
end)
end
if actions.enter then
button.MouseEnter:Connect(function()
actions.enter(button)
end)
end
if actions.leave then
button.MouseLeave:Connect(function()
actions.leave(button)
end)
end
end
function mod.handle_all_buttons(container, actions)
for _, button in ipairs(container:GetChildren()) do
if button:IsA("ImageButton") then
mod.handle_button(button, actions)
end
end
end
return mod
--LocalScript in StarterPlayerScripts
task.wait(3) --just a stall for this test, GUI setup time
local player = game.Players.LocalPlayer
local mod = require(game.ReplicatedStorage:WaitForChild("MyModule"))
local gui = player:WaitForChild("PlayerGui"):WaitForChild("MainUI")
local bar = gui:WaitForChild("BottomBar"):WaitForChild("Container"):WaitForChild("Bar")
mod.handle_all_buttons(bar, {
click = function(button)
print("Clicked:", button.Name)
end,
enter = function(button)
print("Hovered:", button.Name)
end,
leave = function(button)
print("Unhovered:", button.Name)
end
})
A quick testing GUI
--LocalScript in StarterPlayerScripts
local player = game.Players.LocalPlayer
local gui = Instance.new("ScreenGui")
gui.Name = "MainUI"
gui.ResetOnSpawn = false
gui.Parent = player:WaitForChild("PlayerGui")
local bottomBar = Instance.new("Frame")
bottomBar.Name = "BottomBar"
bottomBar.Size = UDim2.new(1, 0, 0, 100)
bottomBar.Position = UDim2.new(0, 0, 1, -100)
bottomBar.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
bottomBar.Parent = gui
local container = Instance.new("Frame")
container.Name = "Container"
container.Size = UDim2.new(1, 0, 1, 0)
container.BackgroundTransparency = 1
container.Parent = bottomBar
local bar = Instance.new("Frame")
bar.Name = "Bar"
bar.Size = UDim2.new(1, 0, 1, 0)
bar.BackgroundTransparency = 1
bar.Parent = container
for i = 1, 3 do
local btn = Instance.new("ImageButton")
btn.Name = "Button" .. i
btn.Size = UDim2.new(0, 100, 0, 60)
btn.Position = UDim2.new(0, 20 + (i - 1) * 120, 0.5, -30)
btn.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
btn.AutoButtonColor = true
btn.Parent = bar
end
This is a subtle Roblox quirk that comes up when connecting UI events from ModuleScripts vs LocalScripts. The key issue is which context the code is running in.
I appreciate the example, but that approach probably won’t change anything. The module is inside PlayerGui and is already being required from a local script (it waits a few seconds before doing so) and then calls _init() , which uses the handle_button function.
function module:_init()
if _init then
return
end
print(`Initiating module {script.Name} ...`)
_init = true
handle_button(buttons.Configuration, configuration)
handle_button(buttons.Thermodynamics, thermodynamics)
handle_button(buttons.Radar, radar)
handle_button(buttons.RobuxShop, robuxshop)
print(`Initiation finalized`)
end
Also, my project is structured around modules handling their own parts of the UI, so I’m trying to keep the connection logic inside those modules. Moving it into a LocalScript wouldn’t really fit that structure, and I don’t think it would fix the issue either.
So even if I followed that setup, it wouldn’t really fix the root issue. The events don’t fire when the connections are made inside the module, but they work fine when connected directly from a local script.
Just to clarify, all of this runs client-side and the issue seems unrelated to context. Everything prints fine, the GUI objects exist, and the connections are made successfully; they just don’t fire.
Yeah, that’s probably the problem. Code running from ModuleScripts inherit the context(?) of the calling script, which means that any functions/threads created in them are treated as dead when the script is destroyed.
I believe a workaround, if you want to keep the same style of your code, would be to fire a BindableEvent that the ModuleScript listens to that creates the desired functions. You can fire the event through the module’s functions, too. It just needs to have the function ran from the ModuleScript’s perspective instead of the script.
I was wondering how you were ever going to get out of this. Broke that down to the only possible issue last night, other than deleting a script. I don’t think I would have ever thought of that.