How can I create custom events?

Hey! :grinning:

I want to learn how to write custom events for a module, here is an example of what I’m trying to accomplish:

local keyboard = require(script.Parent.UserInput.Keyboard)

keyboard.keyDownUp:Connect(function(key) --// keyDownUp would be my custom event
    --// Code here
end)

I hope this is clear enough, any help would be greatly appreciated!

5 Likes

Inside of the module script you would do something like,

keyboard.EventName = Instance.new("BindableEvent")

And then in your example you would do,

keyboard.EventName.Event:Connect(function(...)
    -- 
end)

You could also do .Event inside of the module when you define the event to make it more like normal events

3 Likes

Thanks for the response!

However I am reaching an error with this line:

keyboard.keyDownUp.Event:Connect(function()

I would recommend @Quenty’s Signal class. You can find the source here.

You would create a publicly accessible Signal in your keyboard module using Signal.new() and would connect to it like this:

keyboard.KeyDownUp:Connect(function(any, arguments, passed, go, here)
    print("KeyDownUp fired!")
end)

I believe the primary benefit of using Signal over BindableEvents is because the Signal class doesn’t try to deep-copy any tables passed through it, they’re just passed by reference. BindableEvents and RemoteEvents make a deep-copy of all arguments before sending them over, leading to issues like this.

7 Likes

You could also use a custom ScriptSignal object that does not use any bindable events, hence you don’t need to worry about disconnecting them and they are inexpensive to create, the only caveat is that you can’t call wait on the signal like bindable events: Is it possible to make a custom RBXScriptSignal with OOP? - #6 by Tiffblocks. I would recommend you wrap the function call in the Fire method of the Signal class in a coroutine so it does not yield.

I don’t mind using BindableEvents, I just don’t understand them, and how to work them to do what I want to accomplish, sadly.

Figured it out! TYSM for everyone who replied!

Strange I figured out how to implement BindableEvent:Wait() in my signal class Using

coroutine.yield()

and

coroutine.resume()

and

coroutine.running()

would you mind posting the answer then?

4 Likes

For People still trying to figure out that liked my comment:

You can do it by creating BindableEvents and returning its .Event property. For Exemple:

-- create a bindable event

local JumpedBindable = Instance.new("BindableEvent")
JumpedBindable.Name = "Jumped"

-- make the code that fires it, in my case im gonna start it
    -- from another already existing event, but you can create your own source:

Humanoid.Jumped:Connect(function() -- (this is a default event from humanoids)
    JumpedBindable:Fire()
end)

-- get the .Event property that is the connectable

local Jumped = JumpedBindable.Event

-- now you can do like:

Jumped:Connect(function()
    print("I jumped")
end)
2 Likes

This is essentially a RBXScriptConnection object wrapper.

Why listen for BindableEvent.Event when you can directly listen for Humanoid.Jumped instead?

Cause the idea is to create a custom event, the Humanoid.Jumped is just the source i used for example, but could be anything else that does not have a default event for too, and that you want to comunicate in your scripts. For another example, i have a heroe’s game and one character uses teleport skills, so there is an event on him called “TeleportStarted” and “TeleportEnded” so anyone can know when it teleported and handle skill interactions. Mainly for the use of other scripts in the own char when Im using Bindable, but in this case I also use a Remote one so other characters can get to know that too.
Also, the source of events can aways be determined by its own source, i mean, where it is fired, but we create events for the sake of organization and encapsulation principles. It wouldnt be cool if you had to search in the PlayerModule where does the character’s jump is handled to start your code from there when it jumps, right? Roblox lets you just get a Jumped event out of the code to start your own code from. Its nice if you use that pattern in your scripts too, it keeps them nice and clean.

2 Likes

That’s not a custom event though, it’s just a nested RBXScriptConnection.

aka custom events.

If you mess around in the player module, you get to know that those default events are made from bindables too.

3 Likes

No, not otherwise known as custom events, a custom event would be you own implementation that imitates the behavior displayed by RBXScriptSignal and RBXScriptConnection objects.

I implore you to refer to my previous question.

Why listen for BindableEvent.Event when you can directly listen for Humanoid.Jumped instead?

That is surelly not what the asker wanted to know though and therefore not what he called “custom event” nor what im calling “custom event”. If you got a problem with the term we cant solve that, we are here for pratical problems.

I already answered the question about the jumped event.

3 Likes

Also, the source of events can aways be determined by its own source, i mean, where it is fired, but we create events for the sake of organization and encapsulation principles. It wouldnt be cool if you had to search in the PlayerModule where does the character’s jump is handled to start your code from there when it jumps, right? Roblox lets you just get a Jumped event out of the code to start your own code from. Its nice if you use that pattern in your scripts too, it keeps them nice and clean.

No offense but this is all gibberish, it means nothing. Just directly listen for the humanoid’s Jumping event, there’s no need to wrap that event inside another.

I don’t think that’s the point he’s trying to make. He’s just giving an example of how you could create a “custom event”. It’s not like his implementation was a serious substitution for humanoid.jump

2 Likes

I apologize, I was on a long hiatus. I marked your reply as the solution. For clarification - I was trying to mimic “custom events” not literally make custom events. I wanted to make a module/framework/api whatever you want to call it and I wanted the implementation to be easy. Pretty much what you said but within a module. Thank you though!

There also the option of creating a “sign function” system if you want to get rid of BindableEvents.

  • Create a table that will store signed functions.
  • Create a method to sign functions to that table. – Connect()
  • Create a method to call all the current signed functions. – Fire()
  • Create a method to remove the functions from the table. – Disconnect()
2 Likes