So, I wanted a way to receive signals from a lot of different scripts without creating a bunch of connections and this is what came up with:
local signal_table = {}
local function RegisterNewSignal(signal: RBXScriptSignal)
signal_table[signal] = {}
signal:Connect(function(...)
for _, func in pairs(signal_table[signal]) do
local call = coroutine.wrap(func)
call(...)
end
end)
end
local module = {}
function module:SignTo(signal: RBXScriptSignal, _function: (any) -> ())
if not signal_table[signal] then
RegisterNewSignal(signal)
end
local key = #signal_table[signal]+1
signal_table[signal][key] = _function
return key
end
function module:SignOff(signal: RBXScriptSignal, key: number)
if signal_table[signal] then
signal_table[signal][key] = nil
end
end
return module
Is there any problem with this system? Would it just be better to connect directly to the signal? Is there anything I should change to improve it?
It looks great, but there are few details that could be adjusted:
Using coroutines for every callback can be overkill, especially if the callbacks are simple and don’t require yielding.
Keeping references to functions in signal_table can prevent them from being garbage-collected if they’re not needed anymore.
I mean, it’s not necessary, but I love adding error handling things so I would suggest considering adding error handling to avoid issues that could stop other callbacks from being executed, like pcall or something like that.
Those things are not necessary, because your module is already pretty clean, but those “advices” will improve it’s memory management and performance in big projects.
Thanks! I’m using coroutines because I want all the functions signed to the signal to run pretty much at the same time (like if they were connected to the original event!). Going to be implementing some more sanity checks on it.
Hey, just wanted to clarify something here, but what your module is doing is a trade off between performance and memory. Technically what you’re doing will result in less memory but will take longer to execute (especially in cases where many 100s of connections are happening on one remote). The memory gains are not sufficient enough as a tradeoff for performance in my experience.
Essentially this module is what Connect already does but internally. The only reason why it would result in more memory is because of the objects it creates for each connection.
tl;dr: Yes, it’s practically better to just connect directly instead of wrapping it like this.
I wasn’t really planning on making 100s of connections, but yeah you’re right. After doing some more testing I realized this system wasn’t very practical and I was better off just using remote events to handle communication between local scripts. I guess what Im looking for is a good way to share variables beetween local scripts without having to use a bunch of events.