Voltar para o Blog
Quest Log

Como Exportar Jogo Godot para Web (HTML5): Build, itch.io e Limitações

Jogo Godot rodando dentro de um navegador web em um setup de desenvolvimento

Guia prático para exportar jogo Godot em HTML5: configure o build web, teste local, publique no itch.io e contorne as limitações reais do navegador.

Como Exportar Jogo Godot para Web (HTML5): Build, itch.io e Limitações

Exportar um jogo Godot para web (HTML5) é a forma mais rápida de colocar seu jogo na frente de gente de verdade. Ninguém baixa instalador de desconhecido, mas todo mundo clica num link que abre o jogo direto no navegador. É por isso que game jam vive de build web: a fricção pra jogar é praticamente zero.

Só que o caminho tem pegadinhas. O build web do Godot 4 exige um renderer específico, precisa de headers HTTP que seu servidor local não manda por padrão, e o navegador impõe limitações que não existem no desktop. Esse tutorial cobre o processo completo: preparar o projeto, exportar, testar localmente, publicar no itch.io e saber de antemão o que o browser não vai te deixar fazer.

Antes de exportar: use o renderer Compatibility

Essa é a decisão que muita gente descobre tarde demais. O Godot 4 tem três métodos de renderização: Forward+, Mobile e Compatibility. Os dois primeiros rodam em cima de Vulkan, que não existe no navegador. O build web só funciona com o renderer Compatibility, que usa WebGL 2.

Se você começou o projeto em Forward+, dá pra trocar em Project Settings > Rendering > Renderer > Rendering Method. Mas entenda o custo: efeitos que dependem do pipeline do Forward+ (SDFGI, certos recursos de iluminação global e pós-processamento mais pesado) simplesmente não existem no Compatibility. Quanto mais cedo você decide que o jogo vai pra web, menos retrabalho visual você tem.

Pra projeto novo que mira web desde o início, crie já com Compatibility selecionado na tela de criação do projeto. Você desenvolve vendo exatamente o que o jogador vai ver.

Um aviso que dói: se o seu projeto é em C#, a versão .NET do Godot 4 não tem suporte oficial de exportação pra web até hoje. Pra publicar no navegador, o caminho é GDScript. Se o jogo já está grande em C#, vale pesar se a versão web justifica portar a base de código.

Baixando os export templates

O editor do Godot não vem com os binários de exportação embutidos. Na primeira vez, você baixa os templates oficiais:

  1. Abra Editor > Manage Export Templates
  2. Clique em Download and Install
  3. Espere terminar (o pacote inclui templates de todas as plataformas)

O template precisa bater exatamente com a versão do editor. Se você atualizar o Godot de 4.4 pra 4.5, baixa de novo. É um erro clássico: o preset reclama de "export template not found" depois de um update e a pessoa acha que quebrou algo.

Criando o preset de exportação web

Com os templates instalados:

  1. Project > Export...
  2. Add... > Web
  3. No campo Export Path, escolha uma pasta vazia (tipo build/web/) e nomeie o arquivo como index.html

O nome index.html não é capricho. O itch.io e a maioria dos hosts esperam que o arquivo principal se chame exatamente assim. Exportar com outro nome e renomear depois funciona, mas nomear certo de primeira evita esquecimento.

Ao exportar, o Godot gera um conjunto de arquivos: o index.html (a página que carrega tudo), um .js (o runtime), um .wasm (a engine compilada em WebAssembly) e um .pck (os dados do seu jogo: cenas, scripts, assets). Todos precisam ir juntos pro servidor. O .pck é onde seu jogo realmente mora, e o tamanho dele define quanto tempo o jogador encara a barra de loading.

Thread Support e o tal do SharedArrayBuffer

No preset web existe a opção Thread Support. Ela define se o build usa threads de verdade no navegador, o que depende de um recurso chamado SharedArrayBuffer. O detalhe: por segurança, o navegador só libera SharedArrayBuffer se o servidor entregar a página com dois headers HTTP específicos (Cross-Origin-Opener-Policy e Cross-Origin-Embedder-Policy).

Na prática a escolha é assim:

  • Thread Support ligado: melhor performance, áudio mais estável, mas o jogo só roda em host que manda os headers certos. O itch.io suporta, mas você precisa ligar uma opção lá (já chego nisso).
  • Thread Support desligado (disponível do Godot 4.3 em diante): roda em praticamente qualquer host estático, sem exigência de header, ao custo de performance. Pra jogo leve de jam, costuma ser a opção com menos atrito.

Se o seu jogo é pequeno e você quer o máximo de compatibilidade, desliga. Se precisa de performance e o host coopera, liga.

Testando localmente: por que dar dois cliques no index.html não funciona

Abrir o index.html exportado direto do explorador de arquivos não roda. O navegador bloqueia, porque a página carregada via file:// não pode buscar o .wasm e o .pck. E servir com um servidor simples qualquer também falha no build com threads, porque falta os headers do SharedArrayBuffer.

O jeito mais fácil é nem montar servidor: o editor do Godot tem um botão de Run in Browser (o ícone de remote debug na barra superior, com o preset web criado). Ele exporta, sobe um servidor local com os headers corretos e abre o navegador. Pra iterar rápido, é isso que eu uso.

Quando você quer testar a pasta exportada de verdade (o build final, do jeito que vai pro ar), um script Python de dez linhas resolve:

# serve.py: servidor local com os headers que o build web do Godot exige.
# Rode na pasta do build e abra http://localhost:8000
import http.server

class Handler(http.server.SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header("Cross-Origin-Opener-Policy", "same-origin")
        self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
        super().end_headers()

http.server.HTTPServer(("localhost", 8000), Handler).serve_forever()

Teste no Chrome e no Firefox no mínimo. O comportamento de áudio e de performance varia entre navegadores mais do que a gente gostaria.

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

Hospedando no itch.io

O itch.io é o lugar padrão pra jogo web indie, e o processo é direto:

  1. Compacte o conteúdo da pasta do build num .zip. O index.html precisa estar na raiz do zip, não dentro de uma subpasta. Esse é o erro número um: zipar a pasta em vez do conteúdo dela.
  2. No itch.io, crie o projeto em Upload new project e, em Kind of project, selecione HTML.
  3. Suba o zip e marque "This file will be played in the browser".
  4. Em Embed options, defina a resolução do viewport igual à resolução base do seu jogo (a que está em Project Settings > Display > Window).
  5. Se você exportou com Thread Support ligado, procure a opção de SharedArrayBuffer support nas configurações de embed e ative. Sem isso, o build com threads não inicia.

Salve, abra a página em modo rascunho e jogue do início ao fim antes de publicar. Teste também numa aba anônima: ela revela problemas que o cache do seu navegador esconde.

Sobre tamanho: o jogador de browser não tem paciência de jogador de Steam. Cada dezena de MB no .pck é gente fechando a aba antes do loading acabar. Comprima texturas, corte assets que não usa, exporte áudio longo em Ogg Vorbis em vez de WAV. Manter o build total em poucas dezenas de MB é uma meta razoável pra jogo de jam.

Limitações do browser que você precisa aceitar

O navegador é uma plataforma com regras próprias. Lutar contra elas é perda de tempo; desenhar o jogo dentro delas funciona.

Performance abaixo do nativo. WebAssembly é rápido, mas não é binário nativo, e o WebGL 2 do Compatibility não tem os recursos do Vulkan. Jogo que roda folgado no desktop pode engasgar na web, principalmente em notebook fraco. Faça profiling no navegador, não só no editor.

Áudio precisa de interação. Navegador não toca som antes do usuário clicar ou tocar na página. O Godot já lida com isso na prática (a tela de loading exige um clique), mas evite depender de áudio nos primeiros instantes e teste se a música realmente começa quando deveria.

Saves vivem no IndexedDB. Tudo que você grava em user:// na web vai parar no IndexedDB do navegador. Funciona normal com FileAccess, sem mudar seu código de save. Mas o jogador que limpa os dados de navegação apaga o save junto. Pra jogo de jam, irrelevante; pra jogo com progressão longa, avise o jogador ou ofereça export do save.

Fechar o jogo não existe. get_tree().quit() não fecha a aba do navegador. Se sua UI tem botão "Sair", esconda ele no build web.

Mobile browser é loteria. O build web roda em celular, mas com performance e estabilidade bem piores que no desktop. Se mobile é prioridade, o caminho sério é o export nativo de Android e iOS.

Adaptando o jogo em runtime

Pra lidar com essas diferenças sem manter dois projetos, detecte a plataforma em runtime. O OS.has_feature("web") retorna true só no build web:

func _ready() -> void:
    if OS.has_feature("web"):
        # No browser não existe "sair do jogo".
        $Menu/BotaoSair.visible = false

E quando precisar conversar com o navegador (abrir um link, por exemplo), o JavaScriptBridge executa JavaScript de dentro do GDScript:

func abrir_pagina(url: String) -> void:
    if OS.has_feature("web"):
        # window.open dentro de um clique do usuário não cai no bloqueador de popup.
        JavaScriptBridge.eval('window.open("%s", "_blank")' % url)
    else:
        OS.shell_open(url)

Com esses dois recursos você cobre a maioria dos ajustes: esconder botão de sair, trocar texto de "pressione qualquer tecla" por "toque na tela", desligar efeito pesado só na web.

Fechando

O fluxo inteiro cabe numa lista curta: renderer Compatibility, templates instalados, preset web exportando como index.html, teste local com os headers certos, zip com o index.html na raiz e upload no itch.io. Depois da primeira vez, exportar de novo leva um minuto.

A parte que separa build que funciona de build que as pessoas jogam é o resto: tamanho de download enxuto, teste em mais de um navegador e respeito às limitações da plataforma em vez de briga com elas. Se você nunca publicou nada, faz isso hoje com qualquer protótipo que você tenha. O primeiro link jogável que você manda pra alguém muda sua relação com terminar jogos.