Voltar para o Blog
Quest Log

Como Integrar seu Jogo Godot com a Steam Usando o GodotSteam: Conquistas, Nuvem e Overlay

Tela de computador mostrando um jogo indie feito na Godot com um popup de conquista desbloqueada no canto da tela

Aprenda a integrar seu jogo Godot com a Steam usando o GodotSteam: conquistas, saves na nuvem e overlay, com codigo GDScript tipado e passo a passo.

Se você está perto de lançar, provavelmente já descobriu uma verdade incômoda: a Godot pura não conversa com a Steam. Não existe um botão mágico para ligar conquistas, saves na nuvem ou o overlay. Para integrar seu jogo Godot com a Steam você precisa de uma ponte, e essa ponte se chama GodotSteam. Neste guia prático você vai instalar o addon, inicializar a API, desbloquear uma conquista, gravar um save na nuvem e ligar o overlay, tudo com GDScript tipado e sem enrolação.

Vamos ser honestos desde o começo: isto é conteúdo para quem já tem (ou está prestes a ter) uma página na Steam. Se você ainda está decidindo se vale a pena, dê um passo atrás e leia primeiro o guia completo de como publicar um jogo na Steam. Se você já está com o pé na porta do lançamento, siga em frente.

Por que a Godot pura não fala com a Steam

A Godot é uma engine de código aberto que não embute nenhuma tecnologia proprietária de terceiros. A Steamworks, por outro lado, é a SDK proprietária da Valve que controla conquistas, nuvem, overlay, multiplayer e microtransações. As duas simplesmente não se conhecem de fábrica.

O GodotSteam resolve isso. Ele é um addon real, gratuito e de código aberto que embrulha a Steamworks SDK e a expõe como uma API amigável para o GDScript. Em vez de escrever C++ e lidar com ponteiros da SDK, você chama funções direto no seu script. Para a Godot 4, o GodotSteam funciona via GDExtension (instalável pela AssetLib ou direto do GitHub), e existem também builds precompiladas do editor caso você prefira uma versão já pronta com tudo integrado.

O que o GodotSteam te dá

Com o addon instalado e a API inicializada, você ganha acesso a praticamente tudo que a Steamworks oferece. Para quem está lançando um jogo indie solo ou de time pequeno, os recursos que realmente importam no dia um são:

  • Conquistas (achievements): aqueles popups de "conquista desbloqueada" que aumentam retenção e dão aquele gostinho de progresso.
  • Saves na nuvem (Steam Cloud): o jogador troca de máquina e o progresso vai junto, sem esforço dele.
  • Overlay: o Shift+Tab que abre o navegador da Steam, convites, screenshots e a lista de amigos por cima do seu jogo.
  • Estatísticas, ranks (leaderboards), Rich Presence e multiplayer para quando você quiser ir além do básico.

Neste guia focamos nos três primeiros, que são o mínimo esperado de qualquer jogo sério na plataforma.

Pré-requisitos: App ID e o App ID de teste 480

Aqui está o pré-requisito que pega muita gente de surpresa. Para usar qualquer recurso da Steam, você precisa de um App ID. E ter um App ID próprio significa ter uma página de loja na Steam, o que exige pagar a taxa do Steam Direct por jogo. Não existe atalho: sem página, sem App ID de verdade.

A boa notícia é que você não precisa esperar pela sua página para começar a programar. Durante o desenvolvimento, use o App ID 480, que é o Spacewar, o jogo de exemplo público da Valve. Com ele você inicializa a API, testa conquistas de exemplo, grava arquivos na nuvem e valida o overlay, tudo sem gastar um centavo. Quando sua página estiver aprovada, você troca o 480 pelo seu App ID real e configura tudo no backend do Steamworks.

Você também vai precisar do cliente Steam instalado e logado na mesma máquina onde roda o jogo. Sem a Steam aberta, o addon não tem com quem conversar.

Instalar o GodotSteam

Existem dois caminhos, e vale entender a diferença:

  1. GDExtension (recomendado para a Godot 4): você mantém o editor padrão da Godot e adiciona o GodotSteam como um plugin. Instale pela AssetLib de dentro do editor procurando por "GodotSteam GDExtension" ou baixe o pacote do repositório oficial no GitHub e coloque na pasta addons/ do seu projeto.
  2. Editor precompilado: uma versão do editor da Godot que já vem com o GodotSteam embutido. É mais direto, mas te prende àquela build específica.

Seja qual for o caminho, coloque também os arquivos da biblioteca da Steam (a steam_api correspondente ao seu sistema) junto do executável, e crie um arquivo steam_appid.txt com o número do App ID (durante o desenvolvimento, 480) na raiz do projeto, ao lado do executável de teste. É esse arquivo que diz para a Steam qual jogo você está fingindo ser.

Como a API do GodotSteam evolui entre versões, confira sempre os nomes exatos dos métodos na documentação oficial do GodotSteam. Os exemplos abaixo são realistas e ilustrativos, mas o nome de uma função pode ter mudado na versão que você baixou.

Próximo nível
Quer aprender isso na prática?

No CursoGame.Dev você sai dos tutoriais soltos e constrói jogos publicáveis, com trilha progressiva, quests práticas e feedback real.

Conhecer a plataforma
+500 alunos4.9/5Garantia 7 dias

Inicializar a API e rodar os callbacks

Todo o resto depende deste passo. Você inicializa a Steam uma vez, no começo do jogo, e a partir daí precisa rodar os callbacks a cada frame para que a Steam entregue as respostas assíncronas (conquistas confirmadas, dados da nuvem chegando, etc.).

Um bom lugar para isso é um autoload (singleton) que fica vivo o jogo inteiro. Repare no GDScript tipado, do jeito que deve ser:

extends Node

var steam_habilitado: bool = false
var steam_id: int = 0
var nome_jogador: String = ""

func _ready() -> void:
    var resposta: Dictionary = Steam.steamInitEx()
    if resposta["status"] == 0:
        steam_habilitado = true
        steam_id = Steam.getSteamID()
        nome_jogador = Steam.getPersonaName()
        print("Steam iniciada para: ", nome_jogador)
    else:
        steam_habilitado = false
        push_warning("Falha ao iniciar a Steam: " + str(resposta["verbal"]))

func _process(_delta: float) -> void:
    if steam_habilitado:
        Steam.run_callbacks()

Alguns pontos importantes:

  • Steam.steamInitEx() devolve um dicionário com o status da inicialização. Versões mais antigas usavam Steam.steamInit(), que retorna um booleano mais simples. Confirme qual existe na sua build.
  • Steam.run_callbacks() precisa rodar todo frame. Se você esquecer disso, nada assíncrono funciona: conquistas parecem travar, dados da nuvem não chegam. É o erro silencioso número um.
  • Guarde o steam_habilitado e cheque antes de qualquer chamada. Assim o jogo não quebra quando alguém roda a build fora da Steam.

Desbloquear uma conquista

Antes de qualquer linha de código, entenda a regra de ouro: a conquista precisa existir no backend do Steamworks antes de você conseguir desbloquear ela. Você entra no painel de parceiro, cria a conquista com um ID (por exemplo ACH_PRIMEIRO_CHEFAO), define ícone e nome, publica, e só então o código consegue mexer nela. O código não cria conquistas, ele apenas dispara as que já foram definidas.

Com a conquista já cadastrada, desbloquear é um passo duplo. Você marca a conquista e, logo em seguida, envia para os servidores:

func desbloquear_conquista(id_conquista: String) -> void:
    if not steam_habilitado:
        return

    var conquistada: bool = Steam.getAchievement(id_conquista)["achieved"]
    if conquistada:
        return

    Steam.setAchievement(id_conquista)
    Steam.storeStats()
    print("Conquista enviada: ", id_conquista)

O detalhe que derruba muita gente é o Steam.storeStats(). O setAchievement só marca a conquista localmente; é o storeStats que empurra tudo para a Valve e faz o popup aparecer. Sem ele, a conquista fica presa e nunca desbloqueia de verdade.

Aqui vale um plano maior: em vez de espalhar chamadas de setAchievement pelo projeto inteiro, centralize a lógica de progresso e desbloqueio num único gerenciador. Se você quer montar isso direito, com condições, contadores e persistência, vale estudar como construir um sistema de conquistas robusto que fale com a Steam por uma camada só.

Salvar na nuvem com Steam Cloud

O Steam Cloud sincroniza arquivos entre as máquinas do jogador automaticamente, desde que você configure a cota e os padrões de arquivo no backend do Steamworks. Do lado do código, a Steam expõe uma "gaveta" de arquivos onde você grava e lê bytes.

Gravar um save é escrever um buffer de bytes com um nome de arquivo:

func salvar_na_nuvem(nome_arquivo: String, dados: Dictionary) -> bool:
    if not steam_habilitado:
        return false

    var json_texto: String = JSON.stringify(dados)
    var buffer: PackedByteArray = json_texto.to_utf8_buffer()
    var sucesso: bool = Steam.fileWrite(nome_arquivo, buffer, buffer.size())
    return sucesso

E ler de volta na hora de carregar:

func carregar_da_nuvem(nome_arquivo: String) -> Dictionary:
    if not steam_habilitado:
        return {}

    if not Steam.fileExists(nome_arquivo):
        return {}

    var tamanho: int = Steam.getFileSize(nome_arquivo)
    var buffer: PackedByteArray = Steam.fileRead(nome_arquivo, tamanho)
    var json_texto: String = buffer.get_string_from_utf8()

    var json: JSON = JSON.new()
    var erro: int = json.parse(json_texto)
    if erro != OK:
        return {}
    return json.data

Repare que o save da nuvem é, na prática, o seu save local com um destino diferente. Se o seu jogo ainda não tem uma estrutura de save decente, resolva isso primeiro: monte um sistema de save e load em Godot bem organizado e depois só troque a camada de escrita para apontar para o Steam.fileWrite. Uma boa arquitetura de save separa "o que salvar" de "onde salvar", e é justamente essa separação que faz a nuvem ser plugável.

Uma dica prática: mantenha o save local funcionando mesmo com a nuvem ativa. Assim, se a Steam estiver offline ou o addon não inicializar, o jogador não perde progresso.

Overlay e próximos passos

O overlay é a parte mais fácil, porque na maior parte dos casos ele simplesmente funciona. Uma vez que a API foi inicializada com sucesso e o jogo roda pela Steam, o Shift+Tab já abre a interface por cima do seu jogo, com convites, screenshots e navegador. Você não precisa escrever quase nada.

O cuidado real está no ciclo de vida do jogo. Quando o overlay abre, muitos jogos pausam automaticamente. Se o seu tem gameplay em tempo real, escute o evento de ativação do overlay e pause o jogo enquanto ele estiver aberto, para o jogador não morrer olhando a lista de amigos:

func _ready() -> void:
    Steam.overlay_toggled.connect(_ao_alternar_overlay)

func _ao_alternar_overlay(aberto: bool, _user_initiated: bool, _app_id: int) -> void:
    get_tree().paused = aberto

Confirme o nome exato do sinal (overlay_toggled ou similar) na documentação da sua versão do GodotSteam, porque esse é o tipo de detalhe que muda entre releases.

Com conquistas, nuvem e overlay no lugar, você tem o pacote mínimo que a comunidade da Steam espera. Os próximos passos naturais, quando sobrar fôlego, são leaderboards para ranquear os jogadores, Rich Presence para mostrar "está no chefão final" na lista de amigos, e a Steam Input para dar suporte decente a controles. Mas nada disso é obrigatório para lançar.

O mais importante: teste com o App ID 480 durante todo o desenvolvimento, valide cada recurso com a Steam aberta e logada, e só troque pelo seu App ID real quando sua página estiver aprovada e as conquistas cadastradas no backend. Assim você chega no dia do lançamento com a integração já rodando redonda, em vez de descobrir problemas com o jogo já na vitrine.

Perguntas frequentes

Preciso pagar para testar a integração com a Steam?

Para publicar de verdade, sim: você precisa de um App ID proprio, o que exige uma pagina na Steam e o pagamento da taxa do Steam Direct. Mas para testar o codigo durante o desenvolvimento voce pode usar o App ID 480 (Spacewar), o jogo de exemplo publico da Valve, sem pagar nada.

O GodotSteam funciona com Godot exportado para o navegador?

Nao. A Steamworks SDK e desktop-only (Windows, macOS e Linux). Builds para navegador (HTML5/Web) ou celular nao conseguem falar com o cliente Steam, entao conquistas, nuvem e overlay so funcionam nas exportacoes para desktop.

Por que minha conquista nao desbloqueia?

Os dois motivos mais comuns: a conquista nao foi criada no backend do Steamworks (o codigo so pode desbloquear conquistas que ja existem la, com o mesmo ID exato) ou voce esqueceu de chamar Steam.storeStats() depois de Steam.setAchievement(). Sem o storeStats, o desbloqueio nao e enviado para os servidores da Valve.

O GodotSteam substitui a Steamworks SDK?

Nao, ele a embrulha. O GodotSteam e um addon que expoe as funcoes da Steamworks SDK para o GDScript. Voce ainda depende da Steam rodando na maquina e de um App ID valido; o addon so faz a ponte entre a Godot e a SDK.

Preciso da conta do jogador logada para testar?

Sim. A integracao depende do cliente Steam aberto e com uma conta logada na mesma maquina. Ao rodar pelo editor com o App ID 480, a Steam trata o jogo de teste como se fosse o Spacewar, entao voce consegue exercitar conquistas e nuvem antes mesmo de ter sua propria pagina.