Navinha


SISTEMA ONLINE
REFIT-DOC // NAVINHA2026

NAVINHA2026 // MANUAL DE REFIT

Guia passo a passo para modernizar a nave: sair do código legado (Input Manager antigo) e instalar os novos sistemas de bordo — Input System, Cinemachine 3 e Camera Shake.

⚙ Unity 6+
🎮 Input System
🎥 Cinemachine 3+
💥 Camera Shake

📋 Briefing da missão

Antes de sair reescrevendo tudo, precisamos entender o que muda e por quê. O projeto atual funciona com o sistema de Input antigo (Input.GetAxis) e não tem câmera dinâmica nem sistema de munição. A missão de hoje é modernizar 4 sistemas da nave:

Movimento
Setas / WASD (eixo H/V)
→ Nave acelera na direção do mouse

Entrada (Input)
Input.GetAxis / GetButtonDown
→ Input System (sem Player Input)

Câmera
Main Camera fixa
→ Cinemachine Camera + Shake

Tiro
Disparo infinito
→ Munição limitada (3–5) + recarga

💡

Conceito rápido: “código legado” é só um jeito chique de dizer “código antigo que ainda funciona, mas usa ferramentas que a Unity está deixando de lado”. A gente não joga tudo fora — a gente troca peça por peça, testando sempre que possível.

MÓDULO 01

Preparar o estaleiro (backup + Unity 6)

Nunca faça cirurgia numa nave sem ter uma cópia de segurança dela. Sempre.

Faça um backup do projeto

Feche o Unity. Copie a pasta inteira do Navinha2026 para outro lugar (pendrive, nuvem, outra pasta) e renomeie para algo como Navinha2026_BACKUP. Se algo der errado, você volta no tempo sem drama.

Instale o Unity 6 (ou mais novo) pelo Unity Hub

Abra o Unity Hub → Installs → Install Editor e escolha a versão Unity 6000.x LTS (ou mais recente). Marque os módulos de build da sua plataforma (ex: Windows/WebGL).

Abra o projeto com o novo Editor

No Hub, clique nos 3 pontinhos ao lado do projeto → Change Editor Version → selecione a versão do Unity 6. O Unity vai avisar que vai converter o projeto — confirme.

⚠️

Fique de olho no Console depois de abrir. É normal aparecerem alguns warnings amarelos de API antiga — anote os que forem errors vermelhos, vamos resolver junto com a reescrita do Player.cs.

MÓDULO 02

Instalar os novos sistemas (pacotes)

Input System e Cinemachine não vêm ativados por padrão — são “peças” que a gente encaixa via Package Manager.

Abra o Package Manager

Menu Window → Package Manager. No topo, troque o filtro de “In Project” para Unity Registry — é a “loja oficial” de pacotes da Unity.

Instale o pacote “Input System”

Pesquise por Input System na lista, clique nele e depois em Install. O Unity vai perguntar se quer reiniciar o Editor para ativar o novo sistema — clique em Yes.

Instale o pacote “Cinemachine”

Ainda no Package Manager, pesquise Cinemachine e instale. No Unity 6, a versão instalada já é a Cinemachine 3.x — a que vamos usar (repare que os nomes dos componentes mudaram em relação à versão 2, isso é importante mais pra frente).

Ative o novo sistema de Input no Player Settings

Vá em Edit → Project Settings → Player → Other Settings. Procure o campo Active Input Handling e mude de Input Manager (Old) para Input System Package (New).

🚨

Isso vai “quebrar” o Player.cs antigo de propósito. Ele usa Input.GetAxis, que só existe no sistema antigo. É esperado dar erro no Console agora — vamos reescrever esse script no Módulo 04. Não se desespere!

MÓDULO 03

Criar o mapa de controles (Input Actions)

Sem o componente Player Input — vamos ler os controles direto no código, do jeito “profissional”.

🎓

Conceito: o que é um “Input Action”? Em vez de escrever no código “quando a tecla W for apertada”, você cria uma ação chamada “Acelerar” e diz quais teclas/botões acionam ela. A vantagem: se um dia você quiser trocar o botão de acelerar do mouse esquerdo para a barra de espaço, muda só no arquivo de Input, sem tocar no código.

Crie o arquivo de ações

No painel Project, clique com o botão direito dentro de Assets/Input/ (crie essa pasta se não existir) → Create → Input Actions. Nomeie o arquivo de NavinhaControls.

Abra o editor de ações e crie o Action Map

Dê duplo clique no arquivo NavinhaControls.inputactions. Na coluna da esquerda (“Action Maps”), clique no + e crie um mapa chamado Nave. Um Action Map é só um “grupo” de controles — tipo um painel de botões dedicado à nave.

Crie as 4 ações da nave

Dentro do Action Map Nave, clique no + na coluna “Actions” quatro vezes e configure assim:

Ação Action Type Control Type Binding sugerido
Mirar Value Vector 2 <Mouse>/position
Acelerar Button Button <Mouse>/leftButton
Frear Button Button <Mouse>/rightButton
Atirar Button Button <Keyboard>/space

Para trocar o “Action Type” e o binding, clique na ação e use o painel Properties/Action à direita. Para adicionar o binding, clique no + ao lado da ação → Add Binding, depois clique em “Listen” e aperte a tecla/botão desejado.

🖱️

Quer deixar acessível pra quem prefere teclado? Adicione um segundo binding em Acelerar para <Keyboard>/w e em Frear para <Keyboard>/s. Clique com o botão direito na ação → Add Binding de novo.

Gere a classe C# (sem usar o componente Player Input!)

Clique no arquivo NavinhaControls.inputactions no painel Project (uma vez, para selecionar — não abrir). No Inspector, marque a caixinha Generate C# Class. Deixe o nome da classe como NavinhaControls e clique em Apply.

Isso cria um script gerado automaticamente que representa seu mapa de controles como uma classe C# comum — é essa classe que vamos instanciar direto no Player.cs, sem precisar arrastar nenhum componente no Inspector.

Salve o Save Asset

Clique em Save Asset no canto superior esquerdo da janela do Input Actions e feche a janela.

MÓDULO 04

Reescrever o Player.cs

Aqui entram as duas mudanças de mecânica: nave que acelera/freia na direção do mouse, e munição limitada.

🚀

Como pensar a nova mecânica: imagina uma nave de verdade no espaço — ela não anda “pra frente/trás/esquerda/direita” feito um personagem de RPG. Ela aponta pra uma direção e acelera nessa direção. Sem atrito no espaço, ela só perde velocidade se você frear de propósito (por isso o freio é gradual, não instantâneo).

Apague o conteúdo antigo do Player.cs e cole o novo código

Abra Assets/Script/Player.cs e substitua tudo por este código. Leia os comentários — eles explicam cada bloco:

Assets/Script/Player.csC#
using UnityEngine;
using UnityEngine.InputSystem;
using Unity.Cinemachine;

[RequireComponent(typeof(Rigidbody2D))]
public class Player : MonoBehaviour
{
    [Header("Movimento")]
    public float aceleracao = 8f;           // força aplicada ao acelerar
    public float velocidadeMaxima = 6f;    // limite de velocidade da nave
    public float frenagem = 4f;           // quão rápido a velocidade cai ao frear
    public float velocidadeRotacao = 720f; // graus/seg. de giro pra mirar no mouse

    [Header("Referências")]
    public Camera cameraDoJogo;

    [Header("Tiro")]
    public GameObject laser;
    public Transform disparo;
    public AudioSource somLaser;
    public int disparosMaximos = 5;     // "pente" de tiros (3 a 5, ajuste no Inspector)
    public float tempoRecarga = 1.5f;    // segundos para recuperar 1 disparo

    [Header("Camera Shake")]
    public CinemachineImpulseSource fonteDeImpacto; // dispara o tremor de câmera

    int disparosAtuais;
    float timerRecarga;

    Rigidbody2D rig;
    Vector2 direcaoMira;
    bool estaAcelerando;
    bool estaFreando;

    NavinhaControls controles; // classe gerada pelo Input Actions (Módulo 03)

    void Awake()
    {
        rig = GetComponent<Rigidbody2D>();
        controles = new NavinhaControls();
    }

    void OnEnable()
    {
        // "Enable" liga o mapa de controles — sem isso, os inputs não são lidos
        controles.Nave.Enable();
        controles.Nave.Atirar.performed += Disparar;
    }

    void OnDisable()
    {
        // sempre desliga junto — evita erros quando o objeto é destruído
        controles.Nave.Atirar.performed -= Disparar;
        controles.Nave.Disable();
    }

    void Start()
    {
        somLaser = GetComponent<AudioSource>();
        disparosAtuais = disparosMaximos;
    }

    void Update()
    {
        LerInput();
        RecarregarMunicao();
    }

    void FixedUpdate()
    {
        // física sempre no FixedUpdate, pra ficar suave e independente de FPS
        Mirar();
        Mover();
    }

    void LerInput()
    {
        estaAcelerando = controles.Nave.Acelerar.IsPressed();
        estaFreando = controles.Nave.Frear.IsPressed();
    }

    void Mirar()
    {
        Vector2 posicaoMouseTela = controles.Nave.Mirar.ReadValue<Vector2>();
        Vector2 posicaoMouseMundo = cameraDoJogo.ScreenToWorldPoint(posicaoMouseTela);

        direcaoMira = (posicaoMouseMundo - rig.position).normalized;
        float anguloAlvo = Mathf.Atan2(direcaoMira.y, direcaoMira.x) * Mathf.Rad2Deg;

        // MoveTowardsAngle gira suavemente até o ângulo alvo, em vez de "teletransportar" a rotação
        float anguloSuave = Mathf.MoveTowardsAngle(rig.rotation, anguloAlvo, velocidadeRotacao * Time.fixedDeltaTime);
        rig.MoveRotation(anguloSuave);
    }

    void Mover()
    {
        if (estaAcelerando)
        {
            // empurra a nave na direção que ela está mirando (o mouse)
            rig.linearVelocity += direcaoMira * aceleracao * Time.fixedDeltaTime;
            rig.linearVelocity = Vector2.ClampMagnitude(rig.linearVelocity, velocidadeMaxima);
        }
        else if (estaFreando)
        {
            // reduz a velocidade aos poucos até zero — freio, não parada brusca
            rig.linearVelocity = Vector2.MoveTowards(rig.linearVelocity, Vector2.zero, frenagem * Time.fixedDeltaTime);
        }
        // se nenhum botão estiver pressionado, a nave mantém a velocidade (inércia espacial)
    }

    void Disparar(InputAction.CallbackContext contexto)
    {
        if (disparosAtuais <= 0) return; // sem munição, sem tiro

        Instantiate(laser, disparo.position, disparo.rotation);
        somLaser.Play();
        disparosAtuais--;
    }

    void RecarregarMunicao()
    {
        if (disparosAtuais >= disparosMaximos) return;

        timerRecarga += Time.deltaTime;
        if (timerRecarga >= tempoRecarga)
        {
            disparosAtuais++;
            timerRecarga = 0f;
        }
    }

    void OnTriggerEnter2D(Collider2D bateu)
    {
        // mantém o "teleporte" nas bordas da tela, igual o original
        if (bateu.gameObject.CompareTag("x"))
            transform.position = new Vector3(transform.position.x * -0.9f, transform.position.y, transform.position.z);

        if (bateu.gameObject.CompareTag("y"))
            transform.position = new Vector3(transform.position.x, transform.position.y * -0.9f, transform.position.z);
    }

    void OnCollisionEnter2D(Collision2D colisao)
    {
        if (colisao.gameObject.CompareTag("Asteroid"))
        {
            // dispara o pulso que o Impulse Listener da câmera vai "sentir"
            fonteDeImpacto?.GenerateImpulse();
        }
    }
}

Entenda o que mudou (recap rápido)

  • Mira: em vez de girar com base no eixo Horizontal/Vertical, a nave sempre aponta pra onde o mouse está.
  • Acelerar: aplica força na direção da mira, com um teto de velocidade (velocidadeMaxima).
  • Frear: não zera a velocidade instantaneamente — usa MoveTowards pra reduzir aos poucos, taxa controlada por frenagem.
  • Tiro: só dispara se disparosAtuais > 0. A cada tempoRecarga segundos, recupera 1 tiro (até o máximo).
  • Sem Player Input: a leitura dos controles é 100% feita chamando os métodos da classe NavinhaControls gerada no Módulo 03 — nenhum componente extra no Inspector.

Configure o Tag “Asteroid”

Selecione o prefab Assets/Prefabs/Asteroid (ou o objeto na cena), e no topo do Inspector, no campo Tag, clique em Add Tag se ainda não existir, crie a tag Asteroid e aplique nesse objeto. É essa tag que o novo OnCollisionEnter2D usa pra saber quando a nave foi atingida.

MÓDULO 05

Instalar a câmera Cinemachine 3

Trocando a câmera fixa por uma câmera “viva”, pronta pra reagir ao jogo.

Crie a Cinemachine Camera

Menu GameObject → Cinemachine → Cinemachine Camera. Isso cria um objeto novo na Hierarchy (algo como CM Camera) e automaticamente adiciona um Cinemachine Brain na sua Main Camera — é o Brain que traduz o que a Cinemachine Camera “pensa” para a câmera real que renderiza a tela.

🧠

Nomenclatura nova: na Cinemachine 2 esse objeto se chamava “Virtual Camera” (CM vcam). Na Cinemachine 3, o nome mudou para Cinemachine Camera. Se você pesquisar tutoriais antigos, tenha isso em mente.

Configure o enquadramento

Selecione a CM Camera. Como o jogo é 2D com câmera fixa olhando para o campo de asteroides, você pode deixar o campo Follow vazio (câmera parada) ou arrastar o Player para acompanhar a nave — teste os dois e veja qual funciona melhor pro seu jogo.

Remova scripts de câmera antigos (se existirem)

Se a Main Camera original tinha algum script de movimento manual, desative ou remova — agora quem manda na câmera é a Cinemachine.

MÓDULO 06

Camera Shake ao ser atingido

O tremor de câmera usa o sistema de “Impulse” da Cinemachine — um emissor (na nave) e um ouvinte (na câmera).

🎓

Conceito: Impulse Source x Impulse Listener. Pensa como rádio: a nave tem um “transmissor” (Impulse Source) que emite um sinal quando leva um golpe. A câmera tem um “receptor” (Impulse Listener) sempre ligado, esperando esse sinal pra tremer. Eles nem precisam se conhecer diretamente — o sinal “viaja pelo ar”.

Adicione o Impulse Listener na câmera

Selecione a CM Camera criada no módulo anterior → Add Component → procure Cinemachine Impulse Listener e adicione.

Adicione o Impulse Source na nave

Selecione o objeto PlayerAdd ComponentCinemachine Impulse Source. Ajuste o campo Impulse Definition → Impulse Shape para algo curto e brusco (o padrão “Bump” funciona bem para impacto de asteroide).

Conecte no Inspector do Player

Ainda com o Player selecionado, olhe o script Player no Inspector. Arraste o próprio objeto Player (ou o componente Impulse Source dele) para o campo Fonte De Impacto.

⚠️

Se o campo Fonte De Impacto ficar vazio, o jogo não vai quebrar (usamos ?. no código pra evitar erro), mas o shake simplesmente não vai acontecer. Sempre confira essa referência.

Ajuste a intensidade (opcional, mas recomendado)

No componente Cinemachine Impulse Listener da câmera, existe um campo Gain — aumente para um tremor mais forte, diminua para algo sutil. Teste em Play até achar o “tapa na tela” ideal, sem exagerar a ponto de atrapalhar a leitura do jogo.

MÓDULO 07

Ajustes finais na cena

Últimos parafusos antes do lançamento.

Confira as referências no Inspector do Player

  • Camera Do Jogo → arraste a câmera real (a que tem o Cinemachine Brain, geralmente a Main Camera).
  • Laser → o prefab do tiro (já existente).
  • Disparo → o Transform de onde o tiro nasce (já existente).
  • Fonte De Impacto → o Impulse Source, configurado no Módulo 06.
  • Disparos Maximos → defina 3 ou 5, como preferir para o balanceamento do jogo.

O Laser.cs não precisa mudar

Repare que Laser.cs já tinha a variável tempoDeVida, que destrói o tiro automaticamente depois de alguns segundos (Destroy(this.gameObject, tempoDeVida)). Ou seja, o requisito de “tiro com tempo de vida” já estava pronto — só faltava limitar a quantidade, o que resolvemos no Player.cs.

Rigidbody2D do Player

No componente Rigidbody2D do Player, mude Gravity Scale para 0 (se ainda não estiver) e deixe Linear Drag em 0, já que agora quem controla a desaceleração é o nosso próprio script de frenagem, não o drag da física.

MÓDULO 08

Checklist de teste final

Aperte Play e confira, um por um:

  • ✅ A nave gira suavemente para acompanhar o mouse, mesmo parada.
  • ✅ Segurando o botão de Acelerar, a nave ganha velocidade na direção do ponteiro, até o limite máximo.
  • ✅ Segurando Frear, a velocidade cai aos poucos — não trava de uma vez.
  • ✅ Soltando os dois botões, a nave mantém a velocidade atual (inércia).
  • ✅ Apertando Atirar, o tiro sai e o contador de munição diminui.
  • ✅ Depois de gastar toda a munição, o botão de atirar não faz nada até recarregar.
  • ✅ Ao colidir com um asteroide, a câmera treme por um instante.
  • ✅ Nenhum erro vermelho aparece no Console.
🛠️

Deu erro “NavinhaControls não existe”? Volte no Módulo 03, passo 4 — confirme que a caixinha Generate C# Class foi marcada e que você clicou em Apply dentro do arquivo .inputactions.

🛠️

Câmera não treme? Confira: (1) a tag do asteroide é exatamente Asteroid; (2) o campo Fonte De Impacto do Player está preenchido; (3) a CM Camera tem o componente Impulse Listener.

// FIM DO MANUAL DE REFIT — Navinha2026 pronta para decolar com Unity 6+, Input System, Cinemachine 3 e Camera Shake.

Tags:

Comments

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Search


Categories


Recent Posts