
O que é um Nó na Godot?
O que é um Nó na Godot?
Quando migrei do Unity para a Godot, o mais difícil de entender foi por que eu não podia colocar vários scripts em um único objeto, como fazia antes.
Bem, na Godot é bem diferente, pois essas responsabilidades são divididas em nós, cada nó pode ter apenas um script. Afinal de contas, o que é um nó na Godot?
Você pode entender mais sobre aqui
Tudo é um nó
Na Godot qualquer coisa pode ser um nó, um tocador de som, um renderizador de sprite, uma lógica de física, e por padrão já vem um monte de nós base para você utilizar no seu jogo, o objetivo é um nó ter uma responsabilidade encapsulada, limitada ao seu escopo, e que possa funcionar por si só.
Os nós filhos são como um MonoBehaviour na Unity, mas com certas diferenças e recomendações de como utilizar para comunicar com outros nós.
E podemos criar uma árvore de nós, que chamamos de cena!
O que é uma Cena?
Acho esse nome muito confuso, pois uma cena pode ser usada de várias formas, uma é para criar um novo nó com vários nós dentro dele, por exemplo um Player, e outra é para fazer a cena do seu jogo, por exemplo uma fase.
Em uma cena você precisa definir um nó raiz, ele que vai ser o nó que vai ter o script que vai ser exposto para o mundo, e que controla seus filhos também.
Utilizando o exemplo de Player, o nó raiz dele vai ser normalmente um CharacterBody2D, pois ele precisa da física, e dentro dele vai ter filhos como: Sprite2D, para renderizar o visual do player, CollisionShape2D, para definirmos a colisão do player, AudioStreamPlayer2D, para tocarmos o som do player, etc.
Pais e filhos
Uma boa maneira de pensar é que o nó pai, normalmente vai ser um agrupador, então ele vai se comunicar com os filhos, já os filhos vão apenas obedecer, raramente um filho vai chamar seu pai, o que ele pode é emitir um sinal, e o pai tem que ser responsável por orquestrar seus filhos.
Um exemplo, temos esse cenário:

Nesse exemplo nunca faça um script para o sprite2d, onde ele pega a referência do Player, e lê uma variável dentro dele para definir sua textura, isso é fazer o filho chamar o pai, em vez disso o pai (Player) precisa definir a textura de seu filho.
Exemplo ruim:
Sprite2D.gd
extends Sprite2D
@export var player: Player
func _ready():
texture = player.texture
Exemplo bom:
Player.gd
class_name Player extends CharacterBody2D
@export var texture: Texture2D
@onready var sprite = $Sprite2D # Como o pai sempre vai saber quem são seus filhos você pode buscar eles pelo nome
func _ready():
sprite.texture = texture
O pai sempre sabe quem são seus filhos, já os filhos não têm certeza de quem são seus pais
E isso é para tudo, um outro exemplo, vamos adicionar um nó de Controller que vai gerenciar os Inputs do player:

O Controller não vai pegar as informações e simplesmente atribuir a uma variável lá no Player, pois ele é o filho, e ele não tem certeza de quem é o pai, por isso podemos usar Sinais!
Controller.gd
extends Node
var direction: Vector2 = Vector2.ZERO
signal attacked()
func _process(_delta: float):
direction = Input.get_vector("left", "right", "up", "down")
if Input.is_action_just_pressed("attack"):
attacked.emit()
Como você pode ver esse script do controller ele nunca chama o player, ele pega os inputs e guarda dentro dele, alguns inputs tipo o ataque que precisa ser chamado em um frame quando ele clica, podemos usar o sinal, já no player podemos fazer isso:
Player.gd
class_name Player extends CharacterBody2D
@onready var controller = $Controller
func _ready():
controller.attacked.connect(attack) # Assim podemos pegar inputs de um único frame
func _process(_delta: float):
movement(controller.direction) # Assim podemos pegar valores do input que são contínuos
# movement e attack implementação omitida
Conclusão
Se você tem essa visão de o que são nós na hora de desenvolver você consegue planejar a arquitetura do seu jogo bem melhor, e pensar em todas as nuances de responsabilidades de cada nó, eu pessoalmente gosto de fazer várias lógicas separadas e colocar como filhos.
Eu, por exemplo, uso um nó Forces no meu player. Ele calcula e guarda todas as forças aplicadas e de onde elas vêm. O Player não precisa saber nada disso ele apenas lê o resultado.
Claro que tudo que falei aqui são boas práticas e te ajudam na hora de desenvolver, mas nada disso é um pecado capital. Dentro de uma cena fechada, onde você controla os dois lados, acessar o pai não vai destruir seu projeto. O problema aparece quando o filho depende de um pai que ele não controla aí ele deixa de ser reutilizável.
- Gustavo Maia Paes
