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:
- Script é componente. Um script C# que herda de
MonoBehaviourfunciona igual a um Rigidbody ou um Sprite Renderer: você adiciona a um GameObject e ele passa a fazer parte daquele objeto. - Você não chama
StarteUpdate. A Unity chama. Seu trabalho é escrever o que acontece dentro deles. - 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
- Na Hierarchy, botão direito, 2D Object > Sprites > Square. Renomeie para
Quadrado. - No Project, crie a pasta
Scriptsdentro deAssets. - Clique com o botão direito dentro de
Scriptse escolha Create > Scripting > MonoBehaviour Script. - O arquivo aparece com o nome selecionado. Digite
Giradore 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.
- Arraste o
Giradordo Project para oQuadradona 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 Giradordeclara a classe. O nome tem que ser igual ao do arquivoGirador.cs, com as mesmas maiúsculas.: MonoBehaviourdiz que a classe herda deMonoBehaviour. É isso que transforma o script em componente e faz a Unity chamarStarteUpdate.StarteUpdatesã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 para180f, 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ó.
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 oKeyboard.Keyboard.currenté o teclado conectado. Pode sernull(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", useisPressed.TrocarCoré um método seu. Separar a ação num método com nome claro deixa oUpdatelegí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.



