Voltar para o Blog
Quest Log

Como Programar na Unity: Seu Primeiro Script em C#

Quadrado colorido girando no centro de uma cena 2D com linhas de código flutuando ao lado

Como programar na Unity do zero: crie o primeiro script C#, entenda MonoBehaviour, Start, Update e Debug.Log e faça um objeto girar e mudar de cor no espaço.

Ferramenta:UnityC#

Como Programar na Unity: Seu Primeiro Script em C#

Programar na Unity é escrever scripts em C# que viram componentes de objetos da cena. Você cria o arquivo pelo Project, ele nasce como uma classe que herda de MonoBehaviour, você arrasta para um objeto e a Unity passa a chamar os métodos dele, como Start e Update, nos momentos certos. Aqui você faz isso do zero, até ter um quadrado que gira sozinho e muda de cor quando você aperta espaço.

O objetivo aqui é a mecânica de como programar na Unity: criar, anexar, configurar pelo Inspector, rodar e ler o que acontece no Console. Não é uma aula de linguagem C#. Variáveis, condicionais e laços aparecem só o necessário, e no final eu indico onde aprofundar.

Como programar na Unity: o que saber antes

Três ideias que deixam todo o resto mais fácil:

  1. Script é componente. Um script C# que herda de MonoBehaviour funciona igual a um Rigidbody ou um Sprite Renderer: você adiciona a um GameObject e ele passa a fazer parte daquele objeto.
  2. Você não chama Start e Update. A Unity chama. Seu trabalho é escrever o que acontece dentro deles.
  3. O Console é o seu melhor amigo. Erro de digitação, referência faltando, valor inesperado: tudo aparece lá.

Pré-requisitos: Unity 6.3 LTS instalada, um editor de código configurado (o Visual Studio vem com a instalação no Windows; se preferir VS Code, veja como configurar o autocomplete antes) e um projeto novo com o template Universal 2D.

Se você ainda não sabe nada de lógica de programação, vale passar antes pelo post de lógica de programação para jogos. Não é obrigatório, mas deixa o código abaixo menos misterioso.

Criar o primeiro script C# e anexar ao objeto

  1. Na Hierarchy, botão direito, 2D Object > Sprites > Square. Renomeie para Quadrado.
  2. No Project, crie a pasta Scripts dentro de Assets.
  3. Clique com o botão direito dentro de Scripts e escolha Create > Scripting > MonoBehaviour Script.
  4. O arquivo aparece com o nome selecionado. Digite Girador e aperte Enter na hora.

O passo 4 é o mais importante do post. A Unity usa o nome que você digita para gerar a classe dentro do arquivo. Se você aperta Enter com o nome padrão e renomeia depois, o arquivo muda de nome, mas a classe lá dentro continua com o nome antigo. Resultado: o editor não consegue adicionar o script e mostra que o nome do arquivo não bate com o da classe.

  1. Arraste o Girador do Project para o Quadrado na Hierarchy (ou selecione o Quadrado e use Add Component > Girador).

Selecione o Quadrado: o Inspector mostra um bloco novo, Girador (Script), embaixo do Sprite Renderer.

Anatomia de um MonoBehaviour

Clique duas vezes no script. O editor de código abre com algo assim:

using UnityEngine;

public class Girador : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

Linha por linha:

  • using UnityEngine; libera as classes da Unity (MonoBehaviour, Debug, Transform, Color...).
  • public class Girador declara a classe. O nome tem que ser igual ao do arquivo Girador.cs, com as mesmas maiúsculas.
  • : MonoBehaviour diz que a classe herda de MonoBehaviour. É isso que transforma o script em componente e faz a Unity chamar Start e Update.
  • Start e Update são métodos que a Unity chama sozinha. Os comentários em inglês do template explicam quando.

Start, Update e Debug.Log

Antes de fazer o objeto girar, confirme que o script está rodando. Arquivo Girador.cs:

using UnityEngine;

public class Girador : MonoBehaviour
{
    private void Start()
    {
        Debug.Log("Girador iniciou no objeto " + gameObject.name);
    }

    private void Update()
    {
        transform.Rotate(0f, 0f, 90f * Time.deltaTime);
    }
}

Salve (Ctrl+S), volte para a Unity e espere a compilação terminar (um indicador gira no canto inferior direito). Aperte Play.

  • O Console mostra "Girador iniciou no objeto Quadrado" uma vez. Isso é o Start.
  • O quadrado gira. Isso é o Update, rodando a cada frame.

Por que Time.deltaTime? O Update roda uma vez por frame, e o número de frames por segundo varia de máquina para máquina. Time.deltaTime é o tempo, em segundos, desde o último frame. Multiplicando 90 por ele, o quadrado gira 90 graus por segundo em qualquer PC, rodando a 30 ou a 144 FPS. Sem isso, o jogo fica mais rápido em máquina mais rápida.

Por que private void em vez de só void? Sem modificador, o C# já considera private. Escrever explícito deixa claro que ninguém de fora chama esses métodos. É um hábito de código limpo, não muda o comportamento.

Debug.Log é a ferramenta de investigação mais simples que existe: imprima o valor que você acha que a variável tem e confira. Use sem vergonha. Existem também Debug.LogWarning (amarelo) e Debug.LogError (vermelho).

Variáveis no Inspector

O 90 escrito direto no código é ruim: para testar outra velocidade, você edita, salva e espera compilar. Vamos expor esse valor no Inspector.

using UnityEngine;

public class Girador : MonoBehaviour
{
    [SerializeField] private float grausPorSegundo = 90f;

    private void Start()
    {
        Debug.Log("Girador iniciou no objeto " + gameObject.name);
    }

    private void Update()
    {
        transform.Rotate(0f, 0f, grausPorSegundo * Time.deltaTime);
    }
}

[SerializeField] faz a Unity mostrar e salvar um campo private no Inspector. Volte para a Unity: o bloco do Girador agora tem o campo Graus Por Segundo (a Unity separa as palavras sozinha). Mude para 360 e aperte Play.

Dois detalhes que pegam todo iniciante:

  • O valor do Inspector vence o do código. O = 90f é só o valor inicial quando o componente é adicionado. Depois disso, vale o que está salvo no Inspector. Se você mudar no código para 180f, o objeto que já tem o script continua com o valor antigo.
  • Mudança em Play Mode é descartada quando você para o jogo. Ajuste no Play para testar, anote o valor bom, pare e digite de novo.

Por que [SerializeField] private e não public? Um campo public também aparece no Inspector, mas fica aberto para qualquer outro script alterar. [SerializeField] private aparece no Inspector e continua protegido no código. É o padrão que você vai ver em projeto profissional.

Até aqui o script é independente e cabe na tela. O primeiro jogo de verdade pede vários scripts conversando entre si: o jogador avisa a UI, o inimigo consulta a vida do jogador, o gerenciador controla o estado do jogo. Saber dividir e conectar scripts sem criar um emaranhado é a habilidade que mais pesa para terminar um jogo, e a que menos aparece nos tutoriais de um vídeo só.

Curso de Unity
Quer fazer seu primeiro jogo na Unity?

No curso de Unity 6 da CursoGame.Dev você vai do zero ao primeiro jogo, com um desafio prático em cada level e suporte individual no WhatsApp quando travar.

Conhecer o curso de Unity
Suporte no WhatsAppAcesso vitalícioGarantia de 7 dias

Ler uma tecla com o Input System

Projetos novos da Unity 6 vêm com o Input System ativo. O jeito mais direto de ler uma tecla nele é pelo Keyboard.current. Versão final do Girador.cs:

using UnityEngine;
using UnityEngine.InputSystem;

public class Girador : MonoBehaviour
{
    [SerializeField] private float grausPorSegundo = 90f;
    [SerializeField] private SpriteRenderer spriteRenderer;
    [SerializeField] private Color[] cores = { Color.white, Color.red, Color.green, Color.cyan };

    private int indiceCor;

    private void Start()
    {
        Debug.Log("Girador iniciou no objeto " + gameObject.name);
    }

    private void Update()
    {
        transform.Rotate(0f, 0f, grausPorSegundo * Time.deltaTime);

        Keyboard teclado = Keyboard.current;
        if (teclado != null && teclado.spaceKey.wasPressedThisFrame)
        {
            TrocarCor();
        }
    }

    private void TrocarCor()
    {
        indiceCor = (indiceCor + 1) % cores.Length;
        spriteRenderer.color = cores[indiceCor];
        Debug.Log("Cor trocada para " + cores[indiceCor]);
    }
}

O que entrou:

  • using UnityEngine.InputSystem; libera o Keyboard.
  • Keyboard.current é o teclado conectado. Pode ser null (num celular sem teclado, por exemplo), por isso a checagem.
  • wasPressedThisFrame é verdadeiro só no frame em que a tecla desceu. Segurar não repete. Para "enquanto estiver apertada", use isPressed.
  • TrocarCor é um método seu. Separar a ação num método com nome claro deixa o Update legível.
  • O % (resto da divisão) faz o índice voltar a 0 depois da última cor.

No Inspector, arraste o próprio Sprite Renderer do Quadrado para o campo Sprite Renderer. A lista Cores já vem preenchida; mude à vontade. Aperte Play e espaço.

Para jogos com controle e teclado ao mesmo tempo, o caminho é usar ações (InputAction) em vez de teclas fixas, mas para o primeiro script o Keyboard.current é o mais claro.

Erros comuns no primeiro script

"Can't add script component ... because the script class cannot be found": o nome da classe não bate com o nome do arquivo, ou existe erro de compilação no Console. Renomeie a classe dentro do código para ficar igual ao arquivo.

Nada acontece e nenhuma mensagem aparece: o script não está no objeto, ou o objeto está inativo. Selecione o objeto e confira o Inspector.

Erro vermelho no Console e o Play não roda: erro de compilação. Clique duas vezes no erro e veja a linha. Os culpados mais comuns são ponto e vírgula faltando, chave } sobrando e letra maiúscula errada (debug.log não existe; é Debug.Log).

NullReferenceException na linha do spriteRenderer.color: o campo ficou vazio no Inspector. Arraste o componente.

"InvalidOperationException: You are trying to read Input using the UnityEngine.Input class": você usou Input.GetKeyDown copiado de tutorial antigo num projeto com Input System. Use o código acima.

O valor mudou no código e não mudou no jogo: o Inspector guarda o valor salvo. Clique no menu de três pontos do componente e use Reset, ou digite o valor novo no Inspector.

O editor de código não sugere nada (sem autocomplete): ele não está ligado ao projeto da Unity. Confira em Edit > Preferences > External Tools se o editor certo está selecionado.

Próximo passo

Faça três variações do Girador sem copiar este post: um que gira mais rápido enquanto você segura espaço (isPressed), um que muda de tamanho com as setas, e um que imprime no Console quantas vezes você trocou de cor. Cada uma obriga você a pensar numa variável nova.

Depois disso, é hora de estudar C# com método. O guia de C# para Unity organiza o que aprender da linguagem e em que ordem, e o post sobre qual linguagem a Unity usa explica onde o Visual Scripting entra nessa história.

Perguntas frequentes

Qual linguagem de programação a Unity usa?

A Unity usa C#. Todo script de jogo é uma classe C#, normalmente herdando de MonoBehaviour. A Unity também tem o Visual Scripting, com blocos visuais, mas o mercado e quase todo material de estudo usam C#.

Por que o nome do arquivo precisa ser igual ao nome da classe?

Porque a Unity liga o arquivo .cs ao componente pelo nome. Se o arquivo se chama Girador.cs e a classe dentro dele se chama Rotacao, o editor não consegue adicionar o script ao objeto e mostra um erro. A diferença de maiúscula e minúscula também conta.

Qual a diferença entre Start e Update?

Start roda uma vez, logo antes do primeiro Update daquele script, e serve para preparar as coisas. Update roda a cada frame enquanto o objeto e o script estiverem ativos, e é onde fica o que precisa acontecer continuamente, como ler teclas e mover objetos.

Input.GetKeyDown funciona na Unity 6?

Só se o projeto estiver usando o Input Manager antigo ou a opção Both em Active Input Handling. Projetos novos da Unity 6 usam o Input System, e o equivalente para a barra de espaço é Keyboard.current.spaceKey.wasPressedThisFrame.