HomeVideos

How to use Signals in Godot 4.6 - Complete Beginner Guide (Event Bus, Await, Private Signals)

Now Playing

How to use Signals in Godot 4.6 - Complete Beginner Guide (Event Bus, Await, Private Signals)

Transcript

538 segments

0:01

Today we're going to cut the cables.

0:03

We're going to start with basic button

0:05

signals, cover the new GDO 4.6 hidden

0:08

signal features, and end by building a

0:10

professional event bus, otherwise known

0:12

as a signal bus. Welcome back to GDO dev

0:15

checkpoint. Today, we're going to tackle

0:16

the lifeblood of GDAU architecture,

0:19

signals. These signals allow nodes to

0:21

send messages that something happened

0:24

without caring who's listening. We're

0:26

going to build a signal survivor

0:27

prototype game. We're going to start

0:29

simple. By the end, we will build a

0:31

global communication network that

0:34

professional indie devs use. First,

0:36

let's use the signals GDAU gives us for

0:38

free. We need a button to keep our

0:40

survivor alive. Now, today we're going

0:42

to be using the new release of 4.6. I'll

0:44

put the link in the description, but

0:46

gdau engine.org you can get this new

0:48

version. Now, over here in a blank

0:50

project, I'm going to create a control

0:52

node scene here. I'll rename this

0:54

control node to game. as a child. For

0:57

this, I'm going to add a button.

1:01

I'm going to set the text to recharge.

1:05

Well, I'm going to anchor this button to

1:07

the middle. Center. Anchor center.

1:11

I'm going to add a another child node.

1:13

Label.

1:15

Take our caps lock off. There we go. Get

1:17

a label. A label text. I'm going to have

1:19

it say

1:22

energy

1:24

zero. I'm also going to center this

1:27

anchor. I'm going to use the move tool

1:30

here. I'm going to drag it up just a

1:32

little bit. Now, with that, I'm going to

1:35

add a script to our loot node game. Add

1:38

script. I'm just going to call game

1:41

create. I'm get rid of this boiler plate

1:44

code here. And then I'm going to select

1:46

this button right here. Now, we're

1:48

coming from older version here. You'll

1:50

notice that the new 4.6 six has

1:51

reorganized its signals in groups

1:54

section here. So now we have signals

1:56

instead of node dock tabs a lot more

2:00

better organized. Now in our signals tab

2:03

here with our button selected we're

2:05

going to double click on this pressed

2:08

signal here and we're going to attach it

2:10

to our game script on button pressed

2:13

connect.

2:15

And now we have our button pressed

2:16

signal connected to our script. And in

2:19

here, we're just going to put in a print

2:20

statement. I say signal received

2:26

recharging.

2:30

Okay. And save the scene. Crl S. Save

2:33

scene as game. That's fine. And up here,

2:36

we're going to F6. We're on current

2:38

scene.

2:40

Then I'm going to pull this up a little

2:42

bit. And we click recharge. We'll see

2:44

down here. Single signal received.

2:47

Recharging.

2:49

I keep doing it. There it goes. Now,

2:52

that kind of signal, what we call that

2:53

is an editor connection. That's great

2:55

for static things that never change like

2:58

your main menu buttons or your options

3:00

buttons. But for things that we need to

3:02

have dynamic, we use code connections

3:05

for everything else, especially gameplay

3:08

mechanics and spawned objects.

3:11

The editor is fine for prototypes, but

3:14

in real games, you often spawn things

3:16

with code. You need to know how to

3:18

connect signals manually. This is going

3:20

to be the syntax you'll use probably 90%

3:23

of the time. Now, back in our signal

3:26

dock here with our button selected,

3:28

we're actually going to disconnect this

3:31

pressed signal. Right click, disconnect.

3:36

Then we're actually delete this

3:38

autocompleted signal it put in for us.

3:42

Go to save the script. Then what we're

3:45

going to do, I come in here and I'm

3:47

going to write a function called on

3:50

recharge

3:51

clicked.

3:54

And that's going to be a return avoid.

3:58

So it's not going to return anything.

4:00

And we're going to print connected

4:04

via toad.

4:07

I'm going to save that. Then we need a

4:09

ready function. Function ready. We'll

4:13

let autocomplete with tab enter down.

4:16

Now the syntax for the connection that

4:19

we want to do through code. Now it's

4:21

going to be a syntax is going to be for

4:24

example it's going to be the node you

4:26

want. It's going to be the signal name

4:28

that you want to use and then we want to

4:31

connect that to the callable function we

4:35

want to connect to it.

4:37

For example, this node here, what we're

4:40

going to use is we're actually connect

4:41

our button node and the signal name

4:43

we're going to use is the pressed and

4:46

then we're going to connect to our

4:47

callable function which is on recharge

4:50

clicked. Okay, so all that. So the money

4:54

symbol we get our path. Always best to

4:56

use autocomplete with this so you don't

4:59

accidentally mistype something. So you

5:01

money symbol a path will pop up. We'll

5:03

select button. Then we want to select

5:06

the press here. I'm going to use the

5:10

pressed signal. Just type in pressed.

5:14

There we go. We want to actually

5:17

then connect to it. So connect. So now

5:20

we're connect to the pressed signal on

5:23

the button. But what do we want to

5:24

connect? We want to connect our function

5:26

which is on recharge

5:30

clicked.

5:32

on this part here. I'm going to make

5:33

this bigger. We'll zoom in.

5:37

Let me get rid of this output real

5:39

quick. Now, we're going to stop here.

5:41

Before we type this, look at the end of

5:42

this function name. We do not need these

5:45

parentheses here. Now, this is one of

5:48

the a common mistake that beginners can

5:50

make. Now, obviously, our editor is

5:52

going to yell at us when we do this and

5:54

tell us this is not actually good

5:56

syntax. But why? Well, if you write the

5:59

parentheses here, you're telling GDAU

6:02

that it wants this right now. So, when

6:04

you write a function name without the

6:06

parenthesis, you're giving GDAU the

6:09

recipe. So, the column. So, we'll delete

6:13

those.

6:14

See, our arrow goes away. Now, that GDAU

6:17

has the recipe. Say that we're baking a

6:19

cake. You're saying, "Hey, here's the

6:22

instructions on how to bake that cake.

6:24

Please follow them later when this

6:27

button is pressed. Now, if you add the

6:30

parentheses, you're saying, "Hey, bake

6:32

this cake right now, right when the

6:36

ready starts, right when the game

6:38

starts, not when you click the button."

6:40

But since the function doesn't actually

6:42

return anything, you're trying to

6:43

connect nothing and that will crash the

6:46

game. So one thing to remember when we

6:48

pass functions into signals and connect

6:51

them function name only

6:54

no parenthesis allowed.

6:57

But with that we're going to save. We'll

6:59

make this smaller.

7:01

Then let's do a test run with F6 or

7:05

click right up here. Now we have our

7:08

Hold this up a bit. I'm going to click

7:10

recharge. And now we're connected via

7:13

code.

7:14

There we are. It's connected via code

7:16

with our connection not with the editor

7:20

but through our code.

7:23

We keep clicking it and there we go.

7:25

Now, what if we want to shout a message?

7:28

We need custom signals. Now, we're going

7:30

to make an energy level dropped out. And

7:32

so, when it changes, we're going to

7:34

broadcast that new value so that we'll

7:36

be able to see it on the screen.

7:39

We'll make this smaller and make this

7:42

bigger. So, the top of this script our

7:46

game script. I'm going to write signal

7:49

and then the definition of the signal is

7:52

going to be energy changed

7:55

and what are we going to put in this

7:57

energy change? Well, the new amount we

7:58

want to pass into it. Now we got a big

8:01

change with signals we get 4.6. We have

8:05

private signals now. So what this means

8:07

if we had a signal without the

8:09

underscore

8:11

then it is visible and it's public.

8:13

Basically, they put an underscore right

8:15

before the signal. Well, that makes it

8:17

private. So, it should not show up in

8:20

your documentation or the class or the

8:23

script that you're writing. And it also

8:25

should not be in the autocomp

8:27

completion. I say should not because

8:29

currently this is actually not working.

8:32

Now, there was some confusion about the

8:34

underscore signals and they're supposed

8:36

to hide them in the autocomplete,

8:40

but accordingly that is not the case.

8:44

It's actually only for the core methods,

8:46

but the script methods that does still

8:50

hide it in the documentation.

8:52

As of now, it does not hide it in your

8:54

autocomplete.

8:57

Well, back into our script, I'm going to

8:59

put an unders in front of energy changed

9:02

here. I'm going to save, but it does

9:05

work for the documentation. So, for

9:08

example, if I write another signal here,

9:10

that's energy changed

9:14

and it's just new amount.

9:16

And then if I go in the documentation

9:18

for this, if I look in the docs, we hit

9:22

F1.

9:24

F1. And then we can search for our

9:26

script game.gd

9:29

right here. And then if we go into our

9:31

script and open it. Now we have our own

9:34

doc for our GDScript. You'll see that

9:37

our energy changed.

9:39

The public one without the underscore is

9:42

here. But the one with the underscore is

9:47

not. So say if we delete that and we put

9:53

a one on the end and save it. Go back to

9:56

our docs. Now we have two. That's a good

10:00

way to hide these from your

10:01

documentation. So if you don't want you

10:04

want them private, you don't want anyone

10:05

to see it. We save the change and back

10:08

and save it. Come back to our docs. Now

10:11

it's gone again. Well, we're going to

10:13

keep it public with no underscore. I'm

10:16

delete this one

10:19

and save the script. Now, underneath

10:22

here, I'm going to add a variable

10:25

energy and it's going to be of type int.

10:28

Set it to 10

10:31

and delete that and save there. I'm

10:35

update this function. I'm going to get

10:36

rid of this print statement here. What

10:38

I'm going to do, I'm going to write in

10:39

energy just be plus= 5. And then when we

10:44

call this function, we're going to

10:46

actually emit this signal that we write

10:49

up here. Energy changed. We do that by

10:51

saying energy energy changed. And then

10:54

we need to emit and we need to emit a

10:57

callable

11:00

of type variable. The variable we're

11:01

going to use is this is going to be the

11:04

energy right here.

11:07

Now we just type in energy.

11:11

So whatever we change this energy to be

11:13

we're going to emit that energy and it's

11:15

become the new energy amount

11:18

right here. Make this bigger. So

11:20

basically what this is doing is emitting

11:23

the signal with the data.

11:27

Now we still need to update the UI. So

11:29

we have a helper function looking all

11:30

right should be function of just update

11:33

label very straightforward the amount we

11:36

want to update the labels with the int

11:39

and it's going to return void

11:43

avoid and then what we want to do here

11:46

is access with the money symbol we're

11:50

going to access the label node right

11:51

here and we're going to access the text

11:54

in that label node change it to energy

11:57

colon space enter concatenate plus

12:00

change the amount into a string. You

12:04

have to do that to put it in the label

12:05

or else it won't work. Make sure we

12:08

string the amount.

12:10

So the label will display the proper

12:11

amount of energy we currently have. And

12:14

for list to work well, we need to

12:15

actually connect to this just like we

12:17

did to the button up here. Back in our

12:20

ready script underneath our button

12:22

connection, we're going to have another

12:23

connection to our actual energy changed

12:26

custom signal we just wrote. So energy

12:30

changed

12:31

and then we just need to connect to it.

12:34

We're going to pass in the recipe,

12:38

not the whole cake, just the recipe to

12:40

give GDAU to say what happens when this

12:44

gets emitted. What we want to happen is

12:46

we want to update the label.

12:49

Let's save that. But when the game

12:52

starts, well, we want to actually update

12:53

the label right away. So, we want to

12:56

give GDAU the whole cake. So, we want to

12:58

make sure it uses not just the recipe,

13:01

but it makes it right away. So, we need

13:03

to actually call this update label right

13:06

away. We need to pass in an amount here.

13:10

We're going to pass in well the energy

13:11

that we set. some energy.

13:15

So this here is making the whole cake.

13:18

This here is giving GDO the recipe to

13:21

make the cake when we call it. I'm going

13:24

to save the scene. Save the script. It's

13:27

going to run it. This button up here

13:30

current scene.

13:32

All right.

13:34

Our energy set to 10. Now we're going to

13:36

click the recharge up by five. You see

13:39

our script back here. Energy plus equals

13:41

5. We're emitting that and adding it to

13:44

our energy in our label.

13:48

So, every time you click it, we get five

13:50

more.

13:51

Now, you've reached a checkpoint. I want

13:53

you to add a timer node to the root node

13:56

of the scene. Turn the auto start to on.

14:00

And then in the script, write a function

14:02

just like we have with the on recharge

14:04

clicked. But where you're going to label

14:07

it is you're going to call it function

14:10

on timer tick. That's going to return

14:14

the void.

14:16

Then inside the function, what we're

14:18

gonna do, I want you to minus the energy

14:23

by one

14:26

and then I want you to emit the energy

14:32

changed

14:37

signal. It's very familiar to the auto

14:40

recharge clicked. Just have to adapt it

14:42

to the energy

14:44

by one. Minusing the energy by one. And

14:47

then just like in the button here,

14:50

connect to the timer

14:52

and then connect to the signal name of

14:54

timeout.

14:57

We'll connect that to that new function

14:59

that we just wrote.

15:02

Go and pause it now. Give it a try.

15:08

We all figure that out. If not, that's

15:10

fine. We'll go and follow along with me.

15:13

So, I'm back in our game node here.

15:16

We're going to right click, add child

15:17

node timer.

15:20

In the timer itself, we're going to go

15:21

to the inspector, turn auto start to on,

15:25

and then in the script,

15:29

I'm going to write a new function on

15:30

timer tick. And to minus the energy by

15:33

one, all I got to do is say energy minus

15:37

equals 1. Then emit the energy changed.

15:40

We're going to do energy changed.

15:43

Then we need to emit the energy

15:48

just like that. So literally quite

15:50

literally just the way we did it here.

15:52

Now we need to connect the timer just

15:55

like we did the button. Money sim timer

16:00

timeout

16:02

connect.

16:04

And we need to connect to the on timer

16:06

tick that we just wrote.

16:09

right there with no parenthesis.

16:12

Go and save that. Then we go and give it

16:15

a try. Run current scene.

16:19

You see our energy ticking down by one

16:22

every second and recharge still works as

16:26

well. Now, a quick tip before the big

16:29

finale. Sometimes you just want to wait

16:31

for a signal once. We can use the

16:33

keyword await for that.

16:36

So, in our ready function at the end

16:38

here, well, we're just going to write

16:40

print and then we're write waiting

16:44

for the player to start.

16:48

Okay. And then we just need to stop the

16:50

timer. So, money symbol timer. Then

16:53

we're going to stop.

16:56

So, if it's auto started, we're going to

16:57

stop it initially and we use the keyword

17:00

await. And we're gonna wait for button

17:04

keyword to money symbol button

17:09

pressed.

17:10

So this way we're just going to wait for

17:12

this press signal to be initialized. So

17:16

when the button is pressed

17:19

finally.

17:20

So this basically pseudo pauses the

17:22

game. Well after the button is pressed

17:24

well we're going to print out game

17:26

started.

17:29

That's a fun way to use signals for for

17:32

anything you really want to wait for a

17:34

button or a time or a countdown or

17:36

otherwise. So after the game is started,

17:38

well, we'll take the title and then

17:40

we're just going to start it. Then the

17:42

countdown will begin

17:44

on our energy levels.

17:47

So save that. We're going to run the

17:49

scene

17:52

and notice here waiting for player to

17:55

start. Energy level is not decreasing.

17:58

It's waiting for us to press this button

18:01

right here. Await button pressed. So

18:03

when we push this button, then our timer

18:06

will start and then it'll start

18:07

decreasing our energy.

18:10

14 13 gain started. Now we can play as

18:14

we did before. Perfect.

18:18

Now from the final boss, the event bus

18:21

or signal bus. Right now, if our energy

18:24

hits zero, we want the game to stop. And

18:26

a game over UI to appear, maybe a sound

18:29

to play if you want. Then connecting all

18:31

these nodes together can get messy. So

18:35

that's what the signal bus is for. It's

18:37

like a global radio station, which you

18:40

can listen to, which all our scripts

18:42

listen to for signal. Back our project

18:45

here. Make this smaller. Just our root

18:48

folder here. Create name script. And I'm

18:51

just going to call it signal bus.

18:54

Signal_bus.

18:56

I'm going double click in there. Let me

18:58

get rid of this boiler plate code. The

19:00

only thing I want in here is signal. And

19:04

we're going to use the on game over.

19:08

That's all we need for now. You can put

19:10

as many as you like in here. We'll go

19:13

and save this. Well, we need to make it

19:16

global. How do we do that? We go with

19:18

our project project settings.

19:21

and go into our globals. We're going to

19:23

set a path with this little folder icon.

19:26

We're going to click on our signal bus

19:28

script we just wrote. Open.

19:31

We want this node name to be signal bus

19:35

just like it is. Should autocomplete

19:37

just like that. Then we're going to add

19:39

now we have it enabled as a global

19:41

variable. That's all we need for now. We

19:44

close that. Now back to our game script.

19:48

going to update our on timer tick

19:51

function. Scroll down now and below the

19:55

energy change emit. What we can do here

19:57

is we're going to ask

19:59

the signal bus and this time for time

20:02

over

20:04

game over. So if the energy is less than

20:07

or equal to zero, we want to do is call

20:11

our signal bus and we want to all the

20:15

signal we wrote the signal bus on game

20:17

over.

20:19

So we're should be right here on game

20:21

over and we want to emit that.

20:25

And when we emit game over, well, we do

20:27

want to stop the timer as well. So money

20:30

symbols timer stop.

20:34

Let's save that. Enter down a couple

20:36

times. And we need another function here

20:39

to handle the game over. So function

20:42

handle game over. Let's give a return

20:48

void. And in this function, well, we're

20:50

going to use our label,

20:53

the money symbol label, and we're change

20:55

the text of the label. Instead of

20:57

displaying the energy, it's going to

20:58

display game over.

21:01

Then we want to disable our button so we

21:03

can't keep giving ourselves edge. So the

21:06

button

21:07

disabled

21:09

equals true.

21:12

Then we're going to print in the output

21:14

that the event bus

21:17

told me to shut down. Perfect. And

21:23

remember none of this will work if we

21:25

don't actually connect to it. So open

21:27

our ready function up here.

21:30

and our signal connections. Well, we

21:33

need to also connect to our signal bus

21:37

on game over

21:39

and connect. And what do we want to what

21:42

recipe do we want to give to this

21:44

connection? Well, the on game over the

21:48

handle game over

21:51

function we just wrote is going to be

21:54

called with this on game over emitted

21:57

signal. Great. going to save that.

22:01

And then let's run this scene.

22:04

Now

22:06

we're not running until we click the

22:07

button with our awaiting signal. Waiting

22:11

play to start. Recharge. All right. Our

22:14

timer is counting down. I'm going to let

22:16

it count to zero.

22:18

All right. Game over. Recharge button is

22:22

disabled.

22:24

The event bus told me to shut down

22:28

that we covered a lot. Built-in signals,

22:31

code connection signals, private signals

22:33

in GTO 4.6F

22:36

and passing data with custom signals,

22:38

the await keyword for signals and

22:40

finally the event bus pattern or signal

22:43

bus pattern for signals. Now this is the

22:46

foundation of clean architecture in

22:48

GDAU. The summary is use editor

22:51

connections like you did in the

22:52

beginning for static things that never

22:54

change like your main menu buttons,

22:56

options, buttons, and then use the code

22:58

connections for everything else,

23:00

especially game mechanics, and spawned

23:02

objects. Now, if you found this helpful

23:05

at all or fun, leave a comment what your

23:07

GDO gamedev goals are. Please like,

23:10

subscribe, and hit that notification

23:12

bell. It really helps out the channel.

23:14

And thank you to our current and past

23:16

Patreon and coffee members. Your

23:17

generous support keeps the channel

23:19

moving. If you want early access to

23:22

tutorials, source code, or suggesting

23:24

future tutorials, please consider

23:26

becoming a member yourself. The links

23:28

are in the description. I'm Spaghetti

23:30

Syntax, and remember, always stay

23:32

curious, and I'll see you at the next

23:35

checkpoint.

Interactive Summary

This video tutorial covers the concept of signals in GDevelop, starting with basic button signals and progressing to more advanced features like custom signals, the `await` keyword, and implementing an event bus. It demonstrates how to connect signals using both the editor and code, explains the difference between editor and code connections, and highlights new features in GDevelop 4.6, such as private signals. The tutorial concludes by showing how to use an event bus for global communication between different parts of a game, facilitating cleaner architecture.

Suggested questions

7 ready-made prompts