SignalBus?
Tags: tutorial, godot, signalbus, gamedev
Published: 2022-08-08 08:10:06

---
title: SignalBus?
published: true
description: A quick starting point to get on the SignalBus pattern for Godot Engine
tags: Tutorial, Godot, SignalBus, GameDev
cover_image: https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/LT_471_%28LTZ_1471%29_Arriva_London_New_Routemaster_%2819522859218%29.jpg/1200px-LT_471_%28LTZ_1471%29_Arriva_London_New_Routemaster_%2819522859218%29.jpg
---

Ok, I'll try to write this post in both [portuguese](#pt) and [english](#en).

### <a name="en"></a> English

Let's go!

What is a `SignalBus` and why all this noise in my head when I think about this pattern and more importantly, how to implement it in [Godot?](https://godotengine.org/)

**So what's the concept on this one?**

Imagine the situation, you made your UI all beautiful and wonderful, you have your level all built up, you even have points to spawn the character throughout the level. Everything is perfect, then you need to connect the player and his life points with the UI.

The initial thought comes to mind, "This is a job for signals!", so at your _level_ you locate the player's _node_ and then connect it to _UI_. Everything works, but now you have a code snippet somewhere (level, player, or UI) that you need to know everyone's details and organize.

So this code is entangled.

For small games, this is not a problem, and particularly, until well advanced in my development I didn't experience any problems, and the solution seemed to me even elegant.

But I've this itch in my head, this noise in my brain, this might be better, but how?

It was then that I heard the term `SignalBus`. Now we have a problem and we're going to solve the problem a little more elegantly, and then we're going to think about the implications of that.

In this case we have a [`Singleton`](https://en.wikipedia.org/wiki/Singleton_pattern), which for the engine is done just by creating a script (which we will call `SignalBus.gd` and add the list of [auto-loads](https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html), that way the script will always be running and it can be called in any other script.

Let's then add something very interesting to our friend signal bus, for example:

```gdscript
#SignalBus.gd
extends Node2D

signal PlayerDamaged(total_hp, current_hp)
```

Pretty short, right?
But what about our player friend?

```gdscript
#Player.gd
class_name Player extends KinematicBody2D
#...
func receive_damage(damage):
  #...
  SignalBus.emit("PlayerDamaged", max_hp, current_hp)
  #...
#...
```

As you can see, the player class only knows about SignalBus, but it doesn't know the UI, it doesn't know the level, and honestly, it doesn't need to. The level also no longer needs to know the player, let alone the UI.

Now let's see the UI class,

```gdscript
#UI.gd
class_name UI extends Control
#...
func _ready(damage):
  #...
  SignalBus.connect("PlayerDamaged", self, "on_update_player_life")
  #...
func on_update_player_life(max, curr):
  # Update ui with actual values
#...
```

Now we have a code that is only coupled to `SignalBus`, with that we can move things to other places and even put more things listening to the player signal.

Imagine that we now have an enemy that waits to hear the player take damage and then shoots? Or we need to put a new animation of shaking the screen when the player takes damage, all this can be done by the same signal that is controlled by our friend `bus`.

### <a name="pt"></a> Português

Vamos lá, 

O que é um `SignalBus` e porque todo esse barulho em minha cabeça quando penso nesse padrão e o mais importante, como implementar ele em [Godot?](https://godotengine.org/)

**Qual a idea por trás?**

Imagine a situação, você fez sua UI toda linda e maravilhosa, você tem seu nível todo construido, você tem até pontos para nascer o personagem ao longo da fase. Tudo é perfeito, aí você precisa conectar o jogador e seus pontos de vida com a UI.

Em seu pensamento inicial vem a mente, "Isso é um trabalho para sinais!", então na sua _nível_ você localiza o _nó_ do jogador e então conecta junto a _UI_. Tudo funciona, mas agora você tem um trecho de código em algum lugar (nível, jogador ou UI) que precisa saber dos detalhes de todo mundo e organizar.

Ou seja, acoplamento de código.

Para jogos pequenos, isso não é um problema, e particularmente, até bem avançado no meu desenvolvimento eu não senti problemas, e a solução me pareceu até mesmo elegante.

Mas eu tinha essa pulga atrás da orelha pensando, isso pode ser melhor, mas como?

Foi então que ouvi o termo `SignalBus`. Agora temos um problema e iremos a solução do problema um pouco mais elegante, e depois vamos pensar nas implicações disso.

Nesse caso temos um [`Singleton`](https://en.wikipedia.org/wiki/Singleton_pattern), que para a engine é feito apenas por criar um script (que vamos chamar de `SignalBus.gd` e adicionar a lista de [auto-loads](https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html), dessa forma o script vai estar sempre em execução e se pode ser chamado em qualquer outro script.

Vamos então adicionar algo bem interessante no nosso amigo busão de sinais, segue o exemplo:

```gdscript
#SignalBus.gd
extends Node2D

signal PlayerDamaged(total_hp, current_hp)
```

Bem curtinho, né?
Mas e o nosso amigo jogador?

```gdscript
#Player.gd
class_name Player extends KinematicBody2D
#...
func receive_damage(damage):
  #...
  SignalBus.emit("PlayerDamaged", max_hp, current_hp)
  #...
#...
```

Como se pode ver, a classe do jogador conhece apenas do SignalBus, mas não conhece o UI, nem conhece o nível, e sinceramente, não precisa. O nível também não precisa mais conhecer o jogador, e muito menos o UI.

Agora vmaos a classe do UI,

```gdscript
#UI.gd
class_name UI extends Control
#...
func _ready(damage):
  #...
  SignalBus.connect("PlayerDamaged", self, "on_update_player_life")
  #...
func on_update_player_life(max, curr):
  # Update ui with actual values
#...
```

Agora temos um código que está acoplado apenas no `SignalBus`, com isso podemos mover coisas para outros lugares e inclusive colocar mais coisas ouvindo o sinal do player. 

Imagine que agora temos um inimigo que espera ouvir o jogador receber dano para então atirar? Ou precisamos colocar uma nova animação de tremer a tela quando o jogador receber dano, tudo isso pode ser feito pelo mesmo sinal que é controlado pelo nosso amigo `bus`.

Espero que tenha gostado desse trecho.

(()=>())()