Condicionais no GDScript: if, elif, else e match

Aprenda condicionais no GDScript com exemplos de jogo: if, elif, else, operadores de comparacao e logicos, o match do Godot 4 e os erros de iniciante.
Condicionais no GDScript: if, elif, else e match
Todo jogo vive tomando decisoes. O player levou dano, ainda esta vivo? A tecla de pulo foi apertada? O inimigo esta patrulhando, perseguindo ou atacando? Cada uma dessas perguntas termina em "faz isso ou faz aquilo", e e exatamente disso que trata este texto. Dominar as condicionais no GDScript e o que permite o seu jogo reagir ao que acontece na tela, em vez de rodar sempre igual. Aqui a gente vai do if mais simples ate o match do Godot 4, sempre com exemplos que rodam dentro de um jogo de verdade, e sempre com o codigo tipado como manda a casa.
Se voce ainda esta assentando os primeiros passos, vale ter a base de logica de programacao para jogos fresca, porque condicional sem nocao de fluxo vira decoreba. Aqui a gente parte do principio de que voce ja sabe criar uma variavel tipada e quer aprender a decidir com ela.
O if: a decisao mais basica de um jogo
Um if roda um bloco de codigo somente quando uma condicao for verdadeira. A estrutura le quase como portugues: se tal coisa, faca tal outra. Veja um caso classico, aplicar dano e checar se o player morreu:
var vida: int = 100
func receber_dano(dano: int) -> void:
vida -= dano
if vida <= 0:
vida = 0
morrer()
Traduzindo: subtrai o dano da vida; se a vida ficou menor ou igual a zero, zera a vida e chama a funcao de morte. Repare que o bloco do if so roda quando a condicao bate. Se a vida continuar positiva, o jogo simplesmente segue em frente. Nesse exemplo nao precisamos de mais nada, um if sozinho resolve.
O coracao de qualquer if sao os operadores de comparacao, que devolvem verdadeiro ou falso. Vale ter os seis na ponta da lingua:
vida == 0 # igual a
vida != 0 # diferente de
vida < 30 # menor que
vida > 30 # maior que
vida <= 0 # menor ou igual a
vida >= 100 # maior ou igual a
Guarde bem essa distincao, porque ela gera o bug numero um de iniciante: = atribui um valor a uma variavel, enquanto == compara dois valores. Escrever if vida = 0 esta errado, o certo dentro de uma condicao e if vida == 0. A Godot avisa nesse caso, mas o erro aparece tanto que vale gravar agora: dentro de if, quase sempre voce quer o ==.
if, elif e else: escolhendo entre varios caminhos
Um if sozinho decide entre fazer ou nao fazer. Quando existe uma acao clara para o caso contrario, entra o else, o "senao". E quando ha varios caminhos possiveis, o elif (contracao de "senao se") encadeia as perguntas. Pense num sistema que classifica o estado do player pela vida:
func estado_do_player() -> String:
if vida > 70:
return "saudavel"
elif vida > 30:
return "ferido"
else:
return "critico"
A Godot testa as condicoes de cima para baixo e para na primeira que for verdadeira. Se a vida for 80, devolve "saudavel" e nem olha o resto. Se for 50, pula o primeiro, cai no elif e devolve "ferido". Se for 10, os dois primeiros falham e sobra o else. Essa ordem importa: como cada galho so e testado se o anterior falhou, voce pode escrever elif vida > 30 sem repetir "e menor que 70", porque nesse ponto ja se sabe que a vida nao passou de 70.
O else e opcional. Se voce nao precisa de uma acao para o caso falso, deixe de fora. Mas quando existe uma escolha do tipo "ou isso ou aquilo", ter o else deixa a intencao explicita e evita que um caso escape sem tratamento.
Operadores logicos: combinando condicoes
Muitas decisoes de jogo dependem de mais de uma coisa ao mesmo tempo. Para isso existem os operadores logicos and, or e not. O and exige que as duas condicoes sejam verdadeiras, o or aceita qualquer uma, e o not inverte um valor booleano.
Um exemplo tipico: so deixar o player pular se ele estiver no chao e ainda tiver folego.
func tentar_pular(no_chao: bool, folego: int) -> void:
if no_chao and folego > 0:
pular()
else:
print("Nao da pra pular agora")
Com and, as duas partes precisam bater. Se o player estiver no ar, ou se o folego for zero, o pulo nao acontece. Ja o or serve para "basta uma". Imagine uma porta que abre com a chave certa ou com um comando de mestre ligado:
func pode_abrir(tem_chave: bool, modo_mestre: bool) -> bool:
return tem_chave or modo_mestre
O not inverte. Ele e util para deixar a leitura natural, tipo travar a acao enquanto uma pausa estiver ativa:
func pode_agir(em_pausa: bool) -> bool:
return not em_pausa
Uma dica de clareza: quando uma condicao comeca a virar um emaranhado de and e or, extraia ela para uma funcao com nome, do jeito que fizemos com pode_abrir e pode_agir. O if fica limpo de ler e a intencao aparece no nome. Se ainda tem duvida sobre declarar os tipos desses parametros e retornos, o artigo sobre variaveis e tipos no GDScript fecha essa base.
Truthiness e o estilo ternario
No GDScript, um if nao aceita so comparacoes explicitas, ele aceita valores que sao interpretados como verdadeiros ou falsos. Isso e o que se chama de truthiness. Um numero diferente de zero e verdadeiro, o zero e falso. Uma String vazia e falsa, uma com texto e verdadeira. E, importante para jogo, um objeto que existe e verdadeiro, enquanto null (nada) e falso.
var alvo: Node2D
func _physics_process(delta: float) -> void:
if alvo:
perseguir(alvo)
Escrever if alvo equivale a perguntar "existe um alvo?". Enquanto alvo for null, o bloco nao roda, e assim que ele apontar para um node de verdade, a perseguicao comeca. Isso evita o erro de tentar mexer num objeto que ainda nao existe.
Para decisoes curtas que so escolhem entre dois valores, o GDScript tem uma forma enxuta, o if de uma linha, que faz o papel do ternario de outras linguagens:
var velocidade: float = 400.0 if correndo else 200.0
Le-se da esquerda para a direita: a velocidade e 400 se correndo for verdadeiro, senao e 200. Para uma escolha simples assim, essa linha unica e mais clara que um if de quatro linhas so para atribuir um valor. Use com parcimonia: se a logica cresce, volte para o if normal, que respira melhor.
Se voce ja se pegou empilhando if dentro de if dentro de if e se perdendo no proprio codigo, saiba que isso e a dor mais comum de quem esta aprendendo sozinho. O problema quase nunca e falta de inteligencia, e falta de um caminho que mostre a ordem certa de aprender cada peca.
O match: o switch do Godot 4
Quando um unico valor decide varios caminhos, encadear muitos elif fica repetitivo. Para esse caso existe o match, o equivalente ao switch de outras linguagens. Ele compara um valor contra uma lista de casos e roda o bloco do primeiro que casar. O exemplo mais natural em jogo e a maquina de estados de um inimigo.
enum Estado { PATRULHA, PERSEGUINDO, ATACANDO, MORTO }
var estado: Estado = Estado.PATRULHA
func atualizar_ia() -> void:
match estado:
Estado.PATRULHA:
patrulhar()
Estado.PERSEGUINDO:
perseguir_player()
Estado.ATACANDO:
atacar()
Estado.MORTO:
pass
_:
print("Estado desconhecido")
O match estado olha o valor de estado e desce comparando com cada caso. Se for PERSEGUINDO, roda so o bloco de perseguir e para ali, sem testar os outros. Repare no underline _ no final: ele e o caso curinga, o "qualquer outra coisa", que funciona como um else do match. E uma rede de seguranca para valores que voce nao previu.
O match brilha com outros valores tambem. Para reagir ao tipo de item que o player pegou:
func usar_item(tipo: String) -> void:
match tipo:
"pocao":
curar(30)
"bomba":
explodir()
"chave":
guardar_chave()
_:
print("Item sem efeito: ", tipo)
E um recurso bacana do match do GDScript e agrupar varios casos numa linha so, separados por virgula. Pense em mapear teclas de movimento:
func reagir_tecla(tecla: String) -> void:
match tecla:
"a", "seta_esquerda":
mover(-1)
"d", "seta_direita":
mover(1)
_:
pass
Aqui tanto "a" quanto "seta_esquerda" caem no mesmo bloco. Isso deixa o codigo enxuto quando varias entradas levam ao mesmo resultado. Como regra de bolso: use if quando a decisao envolve condicoes livres e combinadas (vida, distancia, folego, tudo junto), e use match quando um unico valor, como o estado ou o tipo, define o caminho. Os dois convivem no mesmo script sem problema.
Aninhando decisoes sem se perder
Condicionais podem morar dentro de condicionais, e isso e comum. Um inimigo que so ataca se o player estiver por perto e de frente combina distancia e alinhamento:
func decidir_acao(distancia: float, de_frente: bool) -> void:
if distancia <= 120.0:
if de_frente:
atacar()
else:
virar_para_o_player()
else:
perseguir_player()
Funciona, mas quanto mais niveis de aninhamento, mais dificil fica de ler. Um truque util e o retorno antecipado: trate os casos de saida primeiro e evite empilhar. O mesmo comportamento com menos identacao fica assim:
func decidir_acao(distancia: float, de_frente: bool) -> void:
if distancia > 120.0:
perseguir_player()
return
if not de_frente:
virar_para_o_player()
return
atacar()
Cada if resolve um caso e sai com return. Quem le desce a lista de situacoes sem precisar rastrear qual chave fecha qual bloco. Nao existe regra absoluta, mas quando o aninhamento passa de dois ou tres niveis, quase sempre da para achatar assim.
Erros de iniciante que valem evitar
Alem do = no lugar de ==, tem outros tropecos que aparecem toda semana em quem esta comecando. O primeiro e a identacao. No GDScript, o que define o que esta dentro do if e o recuo com Tab, nao chaves. Se voce alinhar errado, um comando pode acabar rodando sempre, fora da condicao, sem a Godot acusar erro. Mantenha a identacao consistente, sempre com Tab, e olhe com atencao o que esta alinhado com o que.
O segundo e esquecer os dois pontos no fim da linha do if, do elif, do else e de cada caso do match. Sem os dois pontos, o codigo nao roda. O terceiro e comparar float com == esperando precisao exata. Numeros decimais podem ter arredondamentos minusculos, entao em vez de if energia == 0.0 prefira if energia <= 0.0, que e mais seguro para valores que descem por subtracao.
Por fim, uma escolha de linguagem que aparece cedo: quem vem de outras linguagens as vezes estranha a sintaxe do GDScript e pensa em usar C#. Se for o seu caso, a comparacao entre C# e GDScript no Godot ajuda a decidir sem achismo. Para aprender condicionais e logica, porem, o GDScript e o caminho mais curto, com feedback rapido dentro do editor.
Por onde seguir
As condicionais no GDScript sao o mecanismo que faz o seu jogo reagir. O if, o elif e o else decidem com base em qualquer condicao, os operadores and, or e not combinam essas condicoes, o truthiness deixa checagens de existencia curtas, e o match organiza a escolha quando um unico valor define o caminho. Nenhuma dessas ideias e exclusiva da Godot, elas aparecem em qualquer motor e linguagem, so muda a escrita.
O jeito de fixar e o de sempre: abra a Godot e escreva. Faca um quadrado que muda de cor quando a vida passa de um limite. Coloque um inimigo com tres estados controlados por um match. Crie um inventario que reage ao tipo de item. Cada pequeno teste transforma a sintaxe em reflexo, e em pouco tempo voce vai olhar para uma mecanica e ja enxergar qual condicional ela pede. A decisao, no jogo e no aprendizado, vem da pratica.
Perguntas frequentes
Qual a diferenca entre if e match no GDScript?
O if avalia qualquer condicao verdadeira ou falsa, inclusive combinacoes com and e or. O match compara um unico valor contra varios casos possiveis, tipo o estado de um inimigo. Use if para condicoes livres e match quando um so valor decide varios caminhos.
Por que meu if nao funciona e a Godot reclama de erro?
O erro mais comum e trocar == por =. O sinal = atribui um valor, o == compara dois valores. Dentro de um if voce quase sempre quer comparar, entao use ==. A Godot avisa quando voce tenta atribuir onde deveria comparar.
Preciso sempre escrever o else?
Nao. O else e opcional. Se voce so quer rodar um bloco quando a condicao for verdadeira e nao fazer nada no caso contrario, um if sozinho basta. O else entra quando existe uma acao clara para o caso falso.


