---
title: "Bevy Engine em Rust: ECS, 2D/3D e Portfólio | Rust Brasil"
url: "https://rustlang.com.br/blog/bevy-engine-ecs-jogos-rust-2026/"
markdown_url: "https://rustlang.com.br/blog/bevy-engine-ecs-jogos-rust-2026.MD"
description: "Guia prático de Bevy em Rust: Entity Component System, sistemas, assets, input, física leve, WebAssembly, testes e como montar um jogo de portfólio em 2026."
date: "2026-09-17"
author: "Equipe Rust Brasil"
---

# Bevy Engine em Rust: ECS, 2D/3D e Portfólio | Rust Brasil

Guia prático de Bevy em Rust: Entity Component System, sistemas, assets, input, física leve, WebAssembly, testes e como montar um jogo de portfólio em 2026.


**Para criar jogos e protótipos interativos em Rust em 2026, comece pelo Bevy quando você quer uma engine data-driven com Entity Component System, renderização moderna via wgpu e um código-base 100% Rust.** Modele o jogo como entidades + componentes + sistemas, separe estado de lógica, carregue assets de forma explícita e só então acrescente física, áudio, UI e export WASM. Não escolha Bevy por moda: escolha quando ECS, iteração em código e controle do loop de frame resolvem o produto melhor do que um editor tradicional.

Bevy já aparece em conversas de [carreira em gamedev com Rust](/carreira/nicho-gamedev/), no panorama de [Rust para jogos](/artigos/rust-para-jogos/) e em comparativos de [GUI e ferramentas](/blog/rust-gui-2026/). Este artigo é o guia operacional: **como estruturar um projeto Bevy de verdade**, o que colocar no primeiro milestone e como transformar isso em sinal de [portfólio](/carreira/portfolio-github/) e [vagas Rust](/vagas/).

## Resposta rápida: Bevy, ggez, macroquad ou engine AAA?

| Necessidade | Escolha inicial | Motivo |
|---|---|---|
| Jogo 2D/3D data-driven com ECS e ecossistema de plugins | **Bevy** | engine completa, schedules, assets e wgpu |
| Protótipo 2D mínimo em poucas horas | **macroquad** / **ggez** | API pequena, feedback imediato |
| Editor maduro, marketplace e time grande | Unity / Unreal | pipeline de conteúdo e hiring mais amplos |
| Ferramenta interna, simulação ou visualizador | Bevy ou [egui](/blog/rust-gui-2026/) | Bevy para cena/tempo real; egui para painéis |
| Demo jogável no browser | Bevy + WASM ou macroquad | WASM viável; cuide do tamanho e dos assets |
| Servidor multiplayer / authoritative sim | Rust + [Tokio](/ecossistema/tokio/) (+ Bevy só no cliente se fizer sentido) | separe simulação de rede da renderização |

Regra prática: se o valor está no **modelo de dados e nos sistemas**, Bevy encaixa. Se o valor está em **arrastar assets num editor** com designers não-programadores no dia um, avalie stacks com editor maduro.

## O que Bevy resolve — e o que não resolve

Bevy organiza o jogo em três ideias:

1. **Entity** — um ID opaco que agrupa componentes;
2. **Component** — dados puros (`Transform`, `Velocity`, `Health`, `Player`);
3. **System** — função que consulta o World e atualiza componentes a cada schedule.

Isso escala melhor do que uma hierarquia rígida de herança de classes de jogo. Novos comportamentos entram como novos componentes e sistemas, não como subclasses intermináveis.

Bevy resolve bem:

- loops de frame com schedules (`PreUpdate`, `Update`, `FixedUpdate`, `PostUpdate`);
- composição de comportamento sem herança profunda;
- renderização moderna via wgpu;
- hot-reload de assets em desenvolvimento;
- plugins reutilizáveis e arquitetura modular;
- demos técnicas, tools e jogos indie em Rust puro.

Bevy não resolve sozinho:

- pipeline de arte AAA com editores visuais maduros;
- hiring em massa de designers acostumados só a Unity/Unreal;
- física AAA completa sem crates/plugins adicionais;
- “jogo pronto” sem disciplina de estados, assets e performance;
- multiplayer autoritativo — rede continua sendo problema de protocolo e simulação.

Se você ainda está consolidando Rust básico, volte ao guia [como aprender Rust](/blog/como-aprender-rust-2026/) e aos [tutoriais](/tutoriais/) antes de brigar com lifetimes dentro de systems complexos.

## Conceitos que você precisa internalizar

### World, Resource e Query

- **World** guarda entidades, componentes e resources.
- **Resource** é estado global (`Time`, `AssetServer`, configuração, score).
- **Query** seleciona entidades que possuem certo conjunto de componentes.

Pense em SQL mental: sistemas são consultas + updates sobre tabelas de componentes. Essa metáfora ajuda em entrevistas e no desenho de features.

### Schedules e ordenação

Nem tudo roda “em qualquer ordem”. Input costuma vir antes da lógica; física em `FixedUpdate`; câmera e UI depois. Quando dois sistemas precisam de ordem, use sets explícitos ou `.before` / `.after`. Ordem implícita vira bug intermitente.

### States

Menu, playing, paused e game over não devem virar `if` espalhado. Use estados do Bevy (ou uma máquina explícita) para spawnar/despawnar entidades e ativar sistemas só no momento certo.

## Projeto inicial: arena 2D com player e inimigos

Um primeiro milestone crível:

```text
bevy-arena/
  Cargo.toml
  assets/
    sprites/
      player.png
      enemy.png
    audio/
      hit.ogg
  src/
    main.rs
    components.rs
    systems/
      mod.rs
      movement.rs
      combat.rs
      spawn.rs
    states.rs
```

Dependências típicas (ajuste a versão à release estável escolhida):

```toml
[package]
name = "bevy-arena"
version = "0.1.0"
edition = "2021"

[dependencies]
bevy = { version = "0.15", features = ["default"] }

[profile.dev]
opt-level = 1

[profile.dev.package."*"]
opt-level = 3
```

Os `opt-level` no profile `dev` são um detalhe prático: Bevy em debug puro fica pesado; otimizar dependências sem abrir mão de rebuilds rápidos do seu crate melhora o feedback loop.

### Componentes como dados

```rust
use bevy::prelude::*;

#[derive(Component)]
struct Player;

#[derive(Component)]
struct Enemy;

#[derive(Component, Deref, DerefMut)]
struct Velocity(Vec2);

#[derive(Component)]
struct Health {
    atual: i32,
    maximo: i32,
}

#[derive(Component)]
struct Collider {
    raio: f32,
}
```

Evite colocar lógica pesada dentro dos componentes. Dados ficam nos componentes; regras ficam nos systems. Essa disciplina facilita testes e refatoração.

### App, plugins e estado

```rust
use bevy::prelude::*;

mod components;
mod states;
mod systems;

use states::GameState;
use systems::{combat, movement, spawn};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                title: "Bevy Arena — Rust Brasil".into(),
                resolution: (960., 540.).into(),
                ..default()
            }),
            ..default()
        }))
        .init_state::<GameState>()
        .add_systems(Startup, spawn::setup_camera)
        .add_systems(OnEnter(GameState::Playing), spawn::spawn_arena)
        .add_systems(
            Update,
            (
                movement::player_input,
                movement::aplicar_velocidade,
                combat::detectar_colisao,
                combat::aplicar_dano,
            )
                .run_if(in_state(GameState::Playing)),
        )
        .run();
}
```

O ponto importante não é o sprite: é a **fronteira clara** entre setup, enter-state, update e condições de execução.

### Movimento com input

```rust
use bevy::prelude::*;
use crate::components::{Player, Velocity};

pub fn player_input(
    teclado: Res<ButtonInput<KeyCode>>,
    mut query: Query<&mut Velocity, With<Player>>,
) {
    const SPEED: f32 = 220.0;
    for mut velocity in &mut query {
        let mut dir = Vec2::ZERO;
        if teclado.pressed(KeyCode::KeyW) || teclado.pressed(KeyCode::ArrowUp) {
            dir.y += 1.0;
        }
        if teclado.pressed(KeyCode::KeyS) || teclado.pressed(KeyCode::ArrowDown) {
            dir.y -= 1.0;
        }
        if teclado.pressed(KeyCode::KeyA) || teclado.pressed(KeyCode::ArrowLeft) {
            dir.x -= 1.0;
        }
        if teclado.pressed(KeyCode::KeyD) || teclado.pressed(KeyCode::ArrowRight) {
            dir.x += 1.0;
        }
        velocity.0 = if dir.length_squared() > 0.0 {
            dir.normalize() * SPEED
        } else {
            Vec2::ZERO
        };
    }
}

pub fn aplicar_velocidade(
    tempo: Res<Time>,
    mut query: Query<(&Velocity, &mut Transform)>,
) {
    for (velocity, mut transform) in &mut query {
        transform.translation.x += velocity.x * tempo.delta_secs();
        transform.translation.y += velocity.y * tempo.delta_secs();
    }
}
```

O padrão a gravar é: **ler input → escrever Velocity → outro system integra no Transform**. Separar “intenção” de “integração” facilita dash, knockback e status effects depois.

> Nota: APIs como `delta_secs()` e nomes de `KeyCode` variam entre releases do Bevy. Trate os snippets como arquitetura; confirme a assinatura na documentação da versão fixada no `Cargo.toml`.

## Arquitetura que escala além do tutorial

### 1. Sistemas pequenos e compostos

Prefira vários systems com uma responsabilidade a um `update_tudo`. Isso melhora paralelismo potencial do ECS, clareza de bugs e testes.

### 2. Events em vez de acoplamento direto

Dano, coleta de item, death e mudança de fase funcionam melhor como events (`EnemyDied`, `PlayerHit`). Systems publicam; outros reagem. Evita queries gigantes e ordem frágil.

### 3. Resources para config e score

```rust
#[derive(Resource)]
struct ArenaConfig {
    largura: f32,
    altura: f32,
    inimigos_iniciais: u32,
}

#[derive(Resource, Default)]
struct Score(u32);
```

Configurações hardcodadas em systems viram dívida. Resources e assets de config deixam balanceamento iterável.

### 4. FixedUpdate para lógica sensível

Movimento casual pode viver em `Update`. Combate, física e simulações que não podem depender do frame time do monitor tendem a `FixedUpdate`. Misturar os dois sem critério produz replays e colisões inconsistentes.

### 5. Despawn e ciclos de vida

Estados devem limpar entidades. Vazamento de entities entre `Menu` e `Playing` é um dos bugs mais comuns em projetos Bevy iniciantes. Ao sair de um estado, despawn explícito ou marcadores de “cleanup” evitam fantasmas invisíveis consumindo CPU.

## Assets, áudio e UI sem drama

- Coloque sprites/áudios em `assets/` e carregue via `AssetServer`.
- Trate handles como dados: spawnar antes do load terminar exige lidar com estados de carregamento.
- UI: comece com a UI do próprio Bevy para HUD (vida, score, pause). Para editores e ferramentas auxiliares, [egui](/blog/rust-gui-2026/) costuma ser mais rápido.
- Áudio: um hit e um tema já bastam no portfólio; volume e mute mostram cuidado de produto.

Se a meta também inclui desktop tool + jogo, diferencie os papéis: Bevy para a cena; toolkit GUI para painéis densos.

## Bevy na web (WASM)

Compilar para browser é um diferencial de demo, não o primeiro passo. Ordem sensata:

1. jogo desktop estável;
2. assets leves e orçamento de tamanho;
3. target WASM e ajustes de input/áudio;
4. hospedagem estática da demo.

Para o contexto mais amplo de WebAssembly em Rust, veja [Rust e WebAssembly](/blog/rust-webassembly-wasm-2026/) e o fluxo de build com [Trunk](/blog/trunk-rust-webassembly-build-deploy-2026/). Em Bevy, WASM é excelência de apresentação; não use isso para esconder arquitetura frágil.

## Testes e qualidade em um projeto de jogo

Jogos parecem “impossíveis de testar”, mas a parte valiosa do Bevy é testável:

- funções puras de dano, score e spawn tables;
- systems rodando em `App` de teste com world controlado;
- asserts sobre componentes após um update;
- golden tests de balanceamento (quantos frames até o player morrer em cenário X).

Exemplo de direção:

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn dano_nao_passa_de_zero() {
        let mut h = Health { atual: 3, maximo: 3 };
        h.atual = (h.atual - 10).max(0);
        assert_eq!(h.atual, 0);
    }
}
```

Suba depois para testes de system com entidades spawnadas. O objetivo não é 100% de cobertura gráfica; é proteger regras de jogo e regressões de estado.

Combine com o hábito geral de [testes em Rust](/blog/testes-rust-estrategias-boas-praticas-2026/) e, se o projeto virar crate público, com tooling de [Cargo](/ecossistema/cargo/).

## Performance: o que medir cedo

- **Quantidade de entities** e queries amplas demais;
- sistemas que rodam sempre sem `run_if`;
- alocações por frame em hot paths;
- sprites/texture atlases sem cuidado;
- logs excessivos em `Update`.

Antes de micro-otimizar, meça com instruments do próprio Bevy/tracing e com um frame budget. Para serviços backend a conversa de profiling é outra — veja [profiling em produção](/blog/rust-profiling-performance-producao-2026/) — mas a mentalidade é a mesma: evidência antes de heroísmo.

## Bevy vs outras opções do ecossistema Rust

| Critério | Bevy | macroquad/ggez | Godot (GDExtension) | Unity/Unreal |
|---|---|---|---|---|
| Modelo mental | ECS data-driven | API imediata | árvore de nós + scripts | editor-first |
| Linguagem principal | Rust | Rust | GDScript/C#/Rust bindings | C#/C++ |
| Curva inicial | média | baixa | baixa/média | baixa para designers |
| Controle do frame | alto | alto | médio | médio |
| Editor visual | limitado/ecossistema | mínimo | forte | muito forte |
| Portfólio Rust “puro” | excelente | bom | híbrido | fraco como sinal Rust |

Para quem mira [empresas que usam Rust](/empresas/) em ferramentas, simulação, infra de jogos ou produtos interativos, Bevy comunica domínio de ECS, schedules e engenharia de runtime. Para quem mira estúdio clássico de games, ainda pesa demonstrar familiaridade com pipelines Unity/Unreal — Bevy sozinho não é passe livre.

## Como montar um portfólio Bevy que ajuda em vagas

Um repositório forte para [carreira Rust](/carreira/) e entrevistas:

1. **GDD de uma página:** objetivo, controles, win/lose, escopo cortado.
2. **Arquitetura:** pasta `systems/`, components claros, states.
3. **Milestone jogável:** 60–90 segundos de loop divertido > mapa enorme vazio.
4. **README:** como rodar, versão do Bevy, screenshots/GIF, decisões e trade-offs.
5. **Testes das regras** + checklist manual de build.
6. **Roadmap honesto:** o que ficou de fora (multiplayer, save, editor).

Sinais que recrutadores entendem rápido:

- input e câmera estáveis;
- spawn/despawn sem vazamento;
- UI de pause/game over;
- configuração separada da lógica;
- commit history limpa.

Combine com o nicho em [gamedev](/carreira/nicho-gamedev/), o panorama de [Rust para jogos](/artigos/rust-para-jogos/) e, se o ângulo for servidor de jogo, com [mensageria](/blog/rust-mensageria-kafka-rabbitmq-nats-2026/) ou redes ([Quinn/QUIC](/blog/quic-quinn-rust-http3-udp-2026/)) no backend — sem forçar Bevy no servidor se não houver ganho.

## Erros comuns (e como evitar)

1. **God system** que move, colide, anima e toca áudio.
2. **Estado global em `static mut`** em vez de Resource.
3. **Ignorar FixedUpdate** em combate/física.
4. **Não fixar versão do Bevy** e copiar snippets de releases diferentes.
5. **Começar pelo WASM** antes do loop divertido no desktop.
6. **Scope creep:** inventário + crafting + árvore de skill no primeiro mês.
7. **Zero medição:** otimizar systems sem saber se CPU ou GPU é o limite.

## Roteiro de 7 dias para o primeiro jogo

| Dia | Entrega |
|---|---|
| 1 | Janela, câmera, sprite do player, movimento |
| 2 | Estados Menu/Playing/GameOver |
| 3 | Inimigos + spawn timer |
| 4 | Colisão e vida |
| 5 | Score, HUD, som de hit |
| 6 | Polimento: reset, dificuldade curta, README |
| 7 | Grava GIF, publica repo, escreve post-mortem de 20 linhas |

Se travar em ownership/borrowing no meio do caminho, pause o jogo e refine a base com [traits](/blog/traits-rust-guia-completo-exemplos/) e os [tutoriais de concorrência](/tutoriais/concorrencia/). Bevy recompensa quem entende dados e lifetimes; pune quem tenta “só mais um `clone`” em todo lugar.

## Perguntas frequentes

### O que é Bevy em Rust?

É uma engine de jogos open source em Rust centrada em ECS, com plugins, assets e renderização via wgpu. Serve a jogos, demos e ferramentas interativas.

### Bevy substitui Unity ou Unreal?

Não de forma geral. Substitui bem em times Rust, protótipos data-driven e produtos onde código e ECS importam mais que o editor. Em pipelines AAA com muitos designers, Unity/Unreal continuam padrão.

### Preciso saber ECS antes de começar?

Não. Aprenda entidades, componentes e sistemas na prática, mas invista cedo em queries, schedules e states para não pintar um beco sem saída.

### Bevy ajuda em portfólio e vagas?

Ajuda quando há jogo jogável, arquitetura legível e README com trade-offs. É um bom sinal para gamedev, tools, simulação e sistemas interativos.

### Bevy roda no navegador?

Sim, via WebAssembly, com cuidados de assets, áudio e tamanho. Faça desktop primeiro.

### Qual versão usar?

A estável mais recente no início do projeto, fixada explicitamente, com notes de migração à mão. Trate upgrades como trabalho de engenharia, não como `cargo update` cego.

## Conclusão

Bevy é a porta de entrada mais convincente para **jogos e protótipos sérios em Rust** quando você topa pensar em ECS, schedules e dados. O caminho maduro é curto e disciplinado: fixe a versão, entregue um loop jogável, separe components/systems/states, teste as regras e documente decisões. Só então busque física avançada, WASM e multiplayer.

Para continuar, releia o panorama de [Rust para jogos](/artigos/rust-para-jogos/), o plano de [carreira em gamedev](/carreira/nicho-gamedev/), o comparativo de [GUI em Rust](/blog/rust-gui-2026/) e explore [projetos práticos](/projetos/) e [vagas](/vagas/) no ecossistema brasileiro. Bevy não é atalho mágico — é uma engine que recompensa engenharia clara.
