Event Systems in Roblox Lua (Part 3 – Better Solution)

Click here for part 2 of this tutorial series. In part 2, we created a simple solution to our problem of creating an event system. We saw there are some problems with this, namely the synchronous execution. One after another, our connected functions are called when the event is fired.

Often times, when you’re using a game engine it’s best to let the engine do the heavy lifting for you. Roblox provides the BindableEvent object to create events in (or out of) the game hierarchy, however it isn’t often that you’ll want to instantiate one every time you want to create a custom event. Let’s create an Event class which uses BindableEvent internally intstead. Let’s re-start with the boilerplate from part 2:

We’re no longer keeping track of the connections ourselves with a table. We’ll merely be passing the connect and fire behaviors onto the already existing functionality of the object. This is quite simple, actually:

The key benefit here: since we’re delegating the responsibility of calling the connected functions to the BindableEvent, it can handle the threading as well. Connected functions that yield will not block other connected functions, so this is a primary benefit from the first simple solution. Note the use of ...  to represent “any and all variables passed to this function”. We’ll talk more about it in part 4.

There is still a problem with this, though. BindableEvents were originally created for inter-script communication. When it comes to tables, there’s some “gotchas”. From the Roblox Wiki article on BindableEvent:

If a Table is passed as an argument to a BindableEvent it must be an array without missing entries or have string keys, not a mixture, or else the string keys will be lost.

This is a big drawback to using a BindableEvent. Your tables will not be the same table as the one you fired the event with. Here’s an example demonstrating this drawback:

You can see that we are firing the event with my_table , then in the connected function comparing that table to (supposedly) itself. This shouldn’t ever throw an error, but it always does due to the described limitations of the BindableEvent.

You’ll also lose metatables, too! So if you created an object using our object-oriented tricks from the previous tutorial, you won’t have an object anymore. Just an empty shell of a table, no purpose, no meaning in life… definitely something you want to avoid.

You can see that the key benefit of letting Roblox handle the threading with the cost of the BindableEvent’s limitations is definitely a trade-off. You can download the finished version of this Event class here. Is it possible to work around this limitation? Maybe. Click here to find out in part 4.