Pular para o conteúdo principal

Aula 10 — Introdução à Unity: Editor, Transformações 3D e Scripting

Objetivos​

Ao final desta aula você deve ser capaz de:

  • Distinguir biblioteca, framework e game engine pelo critério de quem controla o laço principal.
  • Descrever a arquitetura em camadas de uma engine, a separação entre runtime e Editor e as etapas do laço de jogo.
  • Comparar Unity, Unreal Engine e Pygame quanto a natureza, linguagem, recursos, licença e perfil de uso, e justificar a escolha de uma delas para um objetivo dado.
  • Explicar o papel da engine no pipeline gráfico de tempo real e como ela se relaciona com o que foi implementado à mão no Módulo 1.
  • Diferenciar projeto, cena, asset e pacote, e localizar assets na janela Project com busca e filtros.
  • Reconhecer as janelas do Editor da Unity e dizer para que serve cada uma.
  • Descrever o modelo de composição GameObject + Component e a hierarquia de cena.
  • Converter raciocínios de coordenadas entre o sistema de mão direita do OpenGL e o de mão esquerda da Unity.
  • Configurar posição, rotação e escala pelo Transform, distinguindo espaço local e espaço do mundo.
  • Relacionar Mesh Filter, Mesh Renderer, Material e Shader com malha, rasterização e modelo de reflexão.
  • Ajustar a câmera (projeção, campo de visão e planos de recorte) reconhecendo o volume de visualização.
  • Escrever um MonoBehaviour que transforma um objeto ao longo do tempo com Time.deltaTime.
  • Controlar um objeto pelo teclado com o Input System e fazer um objeto orbitar outro com RotateAround, relacionando a órbita à composição translação → rotação → translação inversa.
  • Diagnosticar os erros mais comuns de quem está começando: nome de classe, espaço da transformação e dependência da taxa de quadros.

Conteúdo​

Retomando: do pipeline manual à engine​

No Módulo 1 a imagem era construída por você: vértices enviados um a um, matrizes empilhadas à mão, câmera definida por gluLookAt, visibilidade resolvida pelo z-buffer que você habilitou, iluminação configurada luz a luz. Nada disso deixa de existir em uma engine — apenas passa a ser configurado por componentes em vez de chamadas de função.

Tempo real é uma restrição de orçamento. Um renderizador offline — traçado de raios de um filme — pode gastar minutos ou horas em um único quadro para perseguir reflexos, refrações e iluminação global. Um aplicativo interativo a 60 quadros por segundo tem 16,7 milissegundos para tudo: entrada, física, lógica de jogo e imagem. Daí a rasterização (a mesma da Aula 03) continuar sendo a base, com aproximações — mapas de sombra, luz pré-calculada, reflexos por sondas — no lugar da simulação completa do transporte de luz.

Game engines: conceitos fundamentais​

Antes de abrir o Editor, vale entender que tipo de ferramenta é a Unity, que alternativas existem e por que ela foi a escolhida para este módulo. Os conceitos desta seção valem para qualquer engine; a Unity é só o caso concreto que vamos usar.

Biblioteca, framework e engine​

As três palavras aparecem misturadas em tutoriais, mas descrevem graus diferentes de "quanto a ferramenta decide por você":

  • Uma biblioteca é um conjunto de funções que o seu programa chama. O controle é seu: você decide o que chamar, quando e em que ordem. O PyOpenGL é uma biblioteca — no Módulo 1, cada glVertex3f foi uma chamada sua.
  • Um framework inverte essa relação: ele controla o fluxo do programa e chama o seu código em pontos previstos. Essa inversão se chama inversão de controle ("não nos chame, nós chamamos você"). Você já usou um: o Qt criava a janela, rodava o laço de eventos e chamava o seu paintGL quando era hora de desenhar (Aula 01).
  • Uma game engine é um framework especializado em aplicações interativas de tempo real. Além de controlar o laço, entrega prontos os subsistemas que todo jogo precisa e que não são específicos de nenhum jogo — renderização, física, áudio, entrada, animação, interface, carga de recursos, empacotamento para várias plataformas — e, quase sempre, um Editor visual para montar o conteúdo.

A fronteira não é rígida: uma biblioteca com muitos utilitários começa a se parecer com um framework. O teste prático tem duas perguntas: quem é dono do laço principal? e quanto do jogo já vem pronto?

BibliotecaFrameworkGame engine
Quem controla o laço principalvocêo frameworka engine
O que já vem prontofunções avulsasa estrutura da aplicaçãoestrutura, subsistemas e ferramentas de autoria
ExemplosPyOpenGL, PygameQt/PySide6Unity, Unreal Engine

Arquitetura em camadas​

Por dentro, uma engine é organizada em camadas, e cada camada usa os serviços da que está abaixo dela. A Figura 1 resume essa organização, simplificada a partir de Gregory (2018).

Cada camada só conversa com a de baixo; o Editor fica ao lado do runtime e produz os dados que ele carrega.

Lendo de baixo para cima:

  • Plataforma — sistema operacional, janela, drivers e a API gráfica. Cada fabricante tem a sua: Direct3D (Windows e Xbox), Metal (Apple), Vulkan (Android e Linux), além do OpenGL que você usou. A engine esconde essas diferenças, e o mesmo projeto gera versões para cada plataforma. O Qt fazia algo parecido, em escala menor, ao criar o contexto OpenGL em qualquer sistema operacional.
  • Núcleo — a matemática (vetores, matrizes, quatérnios), a gerência de memória e de recursos, o relógio, o laço principal e a representação da cena como grafo de objetos.
  • Subsistemas — renderização (o pipeline do Módulo 1, agora programado por shaders), física e colisão, áudio, entrada, animação e interface. São módulos independentes que se apoiam no núcleo.
  • Código do jogo — o que é específico daquele jogo: regras, comportamento dos inimigos, pontuação. É a única camada que você escreve.
  • Editor — fica ao lado do runtime, não em cima dele. É a ferramenta que produz os dados que o runtime carrega; o jogo entregue ao jogador não contém o Editor.

Runtime, Editor e dados​

O runtime é a parte da engine que roda dentro do jogo publicado; o Editor é a ferramenta de autoria que o desenvolvedor usa. Essa separação revela uma característica central das engines modernas: elas são orientadas a dados (data-driven). A maior parte de um jogo não é código, e sim dados — a posição de cada objeto, o material de cada superfície, a cor de cada luz, as curvas de cada animação — guardados em arquivos que o runtime lê. Mudar o jogo, na maior parte das vezes, é mudar dados, sem recompilar nada.

Um asset é qualquer recurso do projeto: modelo 3D, textura, som, cena, material. Ao entrar no projeto, o arquivo original (PNG, OBJ, FBX, WAV) passa por um pipeline de importação que o converte para um formato interno otimizado para a plataforma de destino — texturas comprimidas para a GPU, malhas com índices, áudio recodificado. O carregador de OBJ da Aula 07 era um pipeline de importação em miniatura: lia um arquivo de texto e o transformava nas listas de vértices e faces que o desenho usava.

O laço de jogo​

Todo aplicativo interativo repete, enquanto estiver aberto, as mesmas três etapas: ler a entrada, atualizar o estado do mundo e desenhar o quadro. Essa repetição é o laço de jogo (game loop), e a Figura 2 mostra a sua forma mínima.

Uma volta do laço produz um quadro; a 60 quadros por segundo, a volta inteira precisa caber em 16,7 ms.

Dois detalhes separam um laço ingênuo do laço de uma engine:

  • Tempo variável e passo fixo. O intervalo entre quadros varia com a máquina e com a cena, então a lógica usa o tempo decorrido desde o quadro anterior (delta time) para que o movimento seja o mesmo em qualquer taxa de quadros. A física, porém, fica instável com passos de tamanho variável — num passo longo demais, uma bola rápida pode atravessar uma parede sem que a colisão seja detectada. Por isso as engines avançam a física em passos fixos (50 por segundo, por padrão, na Unity), executando zero, um ou vários passos por quadro conforme o tempo acumulado (Fiedler, 2004).
  • Quem escreve o laço. Com uma biblioteca, você escreve o laço inteiro. Com uma engine, o laço é dela; você só preenche os ganchos que ela chama em cada etapa. Na Unity, esses ganchos são métodos como Update e FixedUpdate, que aparecem mais adiante nesta aula.

Quem fez o desafio de animação da Aula 01 já esteve perto disso: um QTimer chamando update() periodicamente, o que por sua vez fazia o Qt chamar paintGL, é um laço de jogo rudimentar — sem entrada, sem física e sem controle de tempo.

Uma breve história​

As engines surgiram quando estúdios perceberam que o código que desenha, toca som e lê o controle podia ser reaproveitado de um jogo para outro, e vendido a outros estúdios.

AnoMarcoPor que importa
1993Doom (id Software)separa o motor (executável) dos dados (arquivos WAD); fases criadas por jogadores mostram que o mesmo motor serve a outro conteúdo
1996Quake (id Software)mundo 3D poligonal em tempo real; o motor é licenciado a outros estúdios — Half-Life (1998) roda sobre um derivado dele
1998Unreal (Epic Games)engine com editor de fases integrado e linguagem de script própria; licenciar engines vira negócio
2000Pygamebiblioteca Python sobre a SDL, criada por Pete Shinners; porta de entrada para jogos em Python
2005Unity 1.0engine com editor acessível a equipes pequenas, lançada inicialmente para Mac OS X
2014–2015Unreal Engine 4código-fonte liberado a assinantes (2014) e, no ano seguinte, uso gratuito com royalties
2015Unity 5edição gratuita com todos os recursos do motor; engines comerciais chegam a estudantes e desenvolvedores independentes
2022Unreal Engine 5Nanite (geometria virtualizada) e Lumen (iluminação global dinâmica)
2023–2024Unity: taxa por instalaçãoanunciada em 2023 e cancelada em 2024 após forte reação da comunidade
2024Unity 6nova numeração; é a série usada neste módulo
2026Unreal Engine 5.8último grande lançamento planejado do UE5; o UE6 foi anunciado, com acesso antecipado previsto para o fim de 2027

Unity, Unreal e Pygame lado a lado​

As três ferramentas aparecem com frequência quando alguém pergunta "com o que eu faço um jogo?". Elas não competem no mesmo terreno — e entender por quê é a melhor forma de escolher.

Unity​

Engine comercial da Unity Technologies, com Editor para Windows, macOS e Linux. A lógica de jogo é escrita em C#, sobre o modelo de composição GameObject + Component que esta aula apresenta adiante. Tem ferramentas dedicadas tanto para 3D quanto para 2D (sprites, Tilemap, física 2D) e dois pipelines de renderização: o URP, leve e multiplataforma, que este módulo usa, e o HDRP, voltado a alta fidelidade visual. Para RV/RA, oferece o XR Interaction Toolkit e o AR Foundation. Publica para desktop, celulares, web, consoles e dispositivos de realidade virtual e aumentada.

Unreal Engine​

Engine da Epic Games, de origem nos jogos de tiro em primeira pessoa e hoje referência em fidelidade visual: Nanite (geometria virtualizada, que permite malhas com milhões de triângulos) e Lumen (iluminação global dinâmica) são os recursos que a tornaram popular também em cinema, produção virtual e visualização arquitetônica. A lógica é escrita em C++ ou em Blueprints, um sistema de programação visual por nós e conexões. O código-fonte completo é acessível a quem aceita a licença (source-available, o que não é o mesmo que open source). O 2D existe (Paper2D), mas é secundário. Com o UE6, a Epic anunciou a migração da programação de jogo para a linguagem Verse.

Pygame​

Não é uma game engine: é uma biblioteca Python que dá acesso à SDL, uma biblioteca em C para janela, desenho 2D, som e entrada. Não tem Editor, grafo de cena, física nem modelo de objetos obrigatório; o laço de jogo é escrito por você. Em troca, é pequena, fácil de instalar e deixa todo o funcionamento à vista, o que a torna ótima para ensino e protótipos. Existem hoje duas linhas: o pygame original e o pygame-ce (Community Edition), um fork mantido pela comunidade e com lançamentos mais frequentes; as duas usam o mesmo import pygame. O 3D só é possível combinando-a com PyOpenGL — ou seja, fazendo à mão o que o Módulo 1 fez.

Comparação​

CritérioUnityUnreal EnginePygame
Naturezagame engine com Editorgame engine com Editorbiblioteca sobre a SDL
Versão de referência (set. 2026)6.3 LTS5.8 (UE6 anunciado)pygame 2.6.1 · pygame-ce 2.5.8
LinguagemC#C++ e BlueprintsPython
Quem controla o laçoa engine (Update, FixedUpdate)a engine (Tick)você (while)
Modelo de objetosGameObject + ComponentActor + Componentlivre: suas classes, com Sprite e grupos opcionais
Sistema de coordenadasmão esquerda, +Y+Y para cimamão esquerda, +Z+Z para cima2D em pixels, yy cresce para baixo
Unidade padrão1 unidade = 1 m1 unidade = 1 cmpixel
2Dferramentas dedicadassecundáriofoco principal
3Dsim; URP (leve) e HDRP (alta fidelidade)sim; foco em alta fidelidadenão nativo (só com PyOpenGL)
Físicaintegrada, 2D e 3Dintegrada (Chaos)não tem; colisão por retângulos
RV/RAXR Interaction Toolkit, AR Foundationsuporte integrado (OpenXR)não
Destinos de publicaçãodesktop, celular, web, consoles, XRdesktop, celular, consoles, XRdesktop
Máquina para desenvolvermodestaexigente (GPU dedicada, muita memória e disco)mínima
LicençaPersonal gratuita até US$ 200 mil de receita e financiamento em 12 mesesgratuita; 5% de royalties sobre a receita bruta de um jogo acima de US$ 1 milhão; gratuita para estudantes e professoreslivre (LGPL)
Código-fonte do motorfechado (parte em C# publicada só para leitura)acessível sob a licençaaberto
Curva de aprendizadomoderadaíngremesuave
Onde é mais comumcelular, estúdios pequenos e médios, 2D, RV/RA, simulaçãojogos de grande orçamento, cinema e produção virtual, arquiteturaensino, protótipos, jogos 2D pequenos
Valores que envelhecem

Versões e termos de licença mudam; os da tabela foram conferidos em setembro de 2026 nas páginas oficiais listadas nas Referências. Antes de uma decisão com consequência comercial, confira a licença vigente.

O mesmo programa em três ferramentas​

Para ver a diferença entre "biblioteca" e "engine" no código, considere o mesmo comportamento nas três ferramentas: um objeto que desliza para a direita com velocidade constante.

Pygame — executável (Python 3.10 ou superior e pip install pygame-ce):

📥 Baixe o arquivo: laco_de_jogo.py

laco_de_jogo.py
import pygame

LARGURA, ALTURA = 640, 360
VELOCIDADE = 200.0 # pixels por segundo


def main() -> None:
pygame.init()
tela = pygame.display.set_mode((LARGURA, ALTURA))
pygame.display.set_caption("Laço de jogo em Pygame")
relogio = pygame.time.Clock()

x, y = 40.0, ALTURA / 2
rodando = True
while rodando: # o laço é seu
dt = relogio.tick(60) / 1000.0 # segundos desde o quadro anterior

for evento in pygame.event.get(): # 1. entrada
if evento.type == pygame.QUIT:
rodando = False

x += VELOCIDADE * dt # 2. atualização
if x > LARGURA + 20:
x = -20.0

tela.fill((30, 30, 40)) # 3. renderização
pygame.draw.circle(tela, (70, 130, 220), (round(x), round(y)), 20)
pygame.display.flip()

pygame.quit()


if __name__ == "__main__":
main()

Unity — somente leitura (o formato completo de um script aparece mais adiante, em "O primeiro script"):

Deslizar.cs
using UnityEngine;

namespace Aula10
{
public class Deslizar : MonoBehaviour
{
[SerializeField] private float velocidade = 2.0f; // unidades (m) por segundo

private void Update() // chamado pela engine uma vez por quadro
{
transform.Translate(Vector3.right * (velocidade * Time.deltaTime), Space.World);
}
}
}

Unreal Engine — somente leitura (trecho; em C++, o header e a implementação ficam em arquivos separados):

Deslizar.h / Deslizar.cpp
// Deslizar.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Deslizar.generated.h"

UCLASS()
class ADeslizar : public AActor
{
GENERATED_BODY()

public:
ADeslizar() { PrimaryActorTick.bCanEverTick = true; }
virtual void Tick(float DeltaTime) override; // chamado pela engine a cada quadro

private:
UPROPERTY(EditAnywhere) float Velocidade = 200.f; // cm por segundo
};

// Deslizar.cpp
#include "Deslizar.h"

void ADeslizar::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
AddActorWorldOffset(FVector(0.f, Velocidade * DeltaTime, 0.f)); // +Y = direita
}

O que a comparação mostra:

  • O mesmo cálculo nas três: posição nova = posição + velocidade × tempo decorrido. dt, Time.deltaTime e DeltaTime são a mesma grandeza.
  • O que some do código: no Pygame você cria a janela, escreve o while, trata eventos, limpa a tela, desenha e troca os buffers (flip) — as três etapas da Figura 2, à vista. Na Unity e na Unreal sobra só a etapa 2; a janela, a câmera, a luz, a malha e o desenho são dados configurados no Editor.
  • O que muda de engine para engine é convenção: a Unreal mede em centímetros e usa +Z+Z para cima, então "direita" é +Y+Y; a Unity mede em metros, com +Y+Y para cima e +X+X para a direita. [SerializeField] e UPROPERTY(EditAnywhere) fazem o mesmo papel: expor o campo no Editor.

Qual ferramenta para qual objetivo​

  • Entender como a imagem é produzida, ou prototipar uma ideia 2D em poucas horas: Pygame — ou OpenGL puro, como no Módulo 1. Você vê cada etapa, mas escreve cada etapa.
  • Jogo 2D ou 3D de escopo pequeno a médio, aplicativo para celular, RV/RA, simulação ou visualização interativa: Unity. É o meio-termo entre recursos prontos e acessibilidade.
  • Fotorrealismo, mundos abertos grandes, produção audiovisual e visualização arquitetônica de alta fidelidade, em equipes maiores e máquinas potentes: Unreal Engine.

Nenhuma escolha é definitiva, porque os conceitos se transferem. Transform e Actor, Update e Tick, câmera com campo de visão e planos de recorte, materiais alimentando shaders: por trás dos nomes está a mesma matemática do Módulo 1. Quem entende o que a engine está fazendo aprende a segunda engine muito mais rápido do que aprendeu a primeira.

Por que a Unity nesta disciplina​

  1. Uma ferramenta para 2D, 3D e RV/RA. O módulo passa por jogos 2D (Aula 12), cenas 3D (Aula 13) e realidade virtual e aumentada (Aula 15), e o projeto prático do módulo, desenvolvido em Unity, admite propostas 2D, 2.5D e 3D. A Unreal é fraca em 2D; o Pygame não faz 3D nem RV/RA.
  2. C# é o degrau certo depois de Python. É uma linguagem gerenciada — a memória é liberada por um coletor de lixo, sem ponteiros manuais — e tipada, com sintaxe próxima de Java. O C++ da Unreal exige gerenciar memória, headers, macros de reflexão (UCLASS, UPROPERTY) e compilações longas; os Blueprints evitam o código, mas escondem justamente a lógica que queremos enxergar.
  3. Os conceitos do Módulo 1 aparecem com o próprio nome. Transform, Camera com Field of View e Clipping Planes, Mesh Filter, Material: a tradução é quase termo a termo (tabela a seguir), e é isso que impede a engine de virar caixa-preta.
  4. Roda em máquinas comuns e nos três sistemas operacionais de desktop. O URP foi pensado para hardware modesto; a Unreal com Nanite e Lumen pede GPU dedicada e bastante memória e disco.
  5. Documentação e comunidade. O manual é versionado por lançamento e há muito material disponível — com a ressalva de que boa parte dele está desatualizada (o template 3D Core, o Input Manager legado). Esta aula aponta esses casos quando eles aparecem.
  6. Licença. A Personal é gratuita para estudo e para projetos pequenos.

O que se deixa de lado, para ser honesto com a escolha: a fidelidade visual de ponta da Unreal; a possibilidade de ler o código do motor; e a independência de fornecedor — o episódio da taxa por instalação, em 2023, mostrou que os termos de uma engine comercial podem mudar de uma hora para outra. É mais um motivo para aprender os conceitos, e não só os menus.

Do Módulo 1 para a Unity​

Cada conceito da Unity que você vai encontrar tem um correspondente no que foi feito à mão no Módulo 1:

No Módulo 1 (OpenGL)Na UnityOnde reaparece
glTranslatef/glRotatef/glScalef + pilha de matrizescomponente Transform e hierarquia de objetosAulas 04 e 06
gluLookAt, glOrtho, gluPerspectivecomponente CameraAula 05
listas de vértices e tabela de facesMesh (Mesh Filter)Aula 07
glEnable(GL_DEPTH_TEST), glCullFaceativados pela engine; ajustáveis por material e por câmeraAula 07
glLight* e glMaterial*componente Light e assets de materialAula 08
laço de desenho escrito por vocêlaço da engine, que chama Update a cada quadroesta aula
Qual pipeline de renderização

O projeto desta disciplina usa o URP (Universal Render Pipeline), o pipeline programável padrão dos projetos 3D da Unity 6. O pipeline fixo que o Módulo 1 usou (OpenGL 2.1) não existe mais aqui: a iluminação é calculada por shaders, programas que rodam na GPU. Você não vai escrever shaders nesta aula, mas vai configurar os materiais que os alimentam.

Ambiente: instalar a Unity e criar o projeto​

A instalação é feita pelo Unity Hub, que gerencia versões do Editor e projetos. O material desta disciplina foi produzido na versão Unity 6.3 LTS (6000.3.24f1). Qualquer patch da 6.3 (6000.3.x) serve. Versões Update da série 6 (6.4 a 6.6) também abrem o projeto, mas mudam pequenos detalhes de tela — e, ao abrir um projeto em uma versão mais nova, a Unity o atualiza para ela, sem caminho de volta. Faça uma cópia antes, ou fique na 6.3.

  1. Instale o Unity Hub, entre com uma conta Unity e ative a licença Personal, que é gratuita. O Hub oferece a ativação no primeiro acesso; se não oferecer, use Settings → Licenses → Add license.
  2. Em Installs → Install Editor, escolha a versão Unity 6.3 LTS. Se o Hub listar um patch mais novo da 6.3, pode instalá-lo; a versão exata de referência está no arquivo de versões da Unity (unity.com/releases/editor/archive), cujo botão de instalação abre o próprio Hub.
  3. Na lista de módulos, nenhum é obrigatório: o Editor já vem com o suporte a gerar executáveis para o sistema em que você trabalha. Documentation instala o manual para uso sem internet; Android Build Support e Web Build Support só são necessários para publicar nessas plataformas. Módulos podem ser acrescentados depois, pelo ícone de engrenagem da versão em Installs → Add modules.
  4. Instale um editor de código. O recomendado é o Visual Studio Code — o Hub pode oferecê-lo na própria lista de módulos — com a extensão Unity, da Microsoft, que instala junto o C# Dev Kit. O template do projeto já traz o pacote de integração (Visual Studio Editor).
  5. Em Projects → New project, selecione a versão 6.3 LTS, o template 3D URP, dê um nome sem acentos e sem espaços e escolha a pasta.
  6. Com o projeto aberto, indique o editor de código em Unity → Settings (macOS) ou Edit → Preferences (Windows e Linux), seção External Tools, campo External Script Editor: escolha Visual Studio Code. A partir daí, clicar duas vezes em um script o abre no VS Code com autocompletar da API da Unity.
Escolha do template

Tutoriais mais antigos mandam criar o projeto com o template 3D ou 3D Core, do pipeline Built-in. O Editor 6.3 traz embutidos apenas três templates — 3D URP, 3D HDRP e Universal 2D — e esta disciplina usa o 3D URP. Materiais feitos para o Built-in (o shader Standard) aparecem em rosa-magenta quando abertos em um projeto URP, sinal clássico de shader incompatível; a conversão é feita em Window → Rendering → Render Pipeline Converter.

O primeiro carregamento demora: a Unity importa e compila os assets do template e abre a cena de exemplo Assets/Scenes/SampleScene. A pasta Library/, gerada nesse processo, é descartável e não entra no controle de versão.

Projeto, cena e asset: como a Unity organiza o trabalho​

Antes de abrir as janelas do Editor, vale fixar três palavras que aparecem em toda instrução daqui em diante.

Projeto é uma pasta do seu disco que a Unity trata como uma unidade: tudo o que o jogo usa e todas as configurações dele. Criar um projeto no Hub cria essa pasta; abrir o projeto é abrir a pasta. Dentro dela:

PastaO que guardaVai para o controle de versão?
Assets/tudo o que você cria ou importa: cenas, scripts, materiais, texturas, modelos, sonssim
Packages/a lista de pacotes do projeto (manifest.json) — URP, Input System etc.sim
ProjectSettings/configurações do projeto: qualidade, física, entrada, versão do Editorsim
Library/cache gerado pela importação dos assets; é refeita se apagadanão
Temp/, Logs/, UserSettings/arquivos temporários, registros e preferências pessoais do Editornão

Os arquivos .csproj e .slnx na raiz também são gerados pela Unity, para o editor de código, e não precisam ser versionados.

Asset é qualquer arquivo dentro de Assets/ que o projeto usa: uma cena, um script, um material, uma textura, um modelo 3D, um som. Como visto em "Runtime, Editor e dados", o arquivo original é importado para um formato interno — e o resultado vai para Library/. Alguns assets são criados pelo próprio Editor (cenas, materiais, scripts); outros chegam de fora (imagens, modelos, áudio) e são importados ao entrar na pasta.

AssetExtensãoOnde aparece nesta disciplina
Cena.unityesta aula
Script C#.csesta aula
Material.matesta aula; Aula 13
Textura.png, .jpgAulas 12 e 13
Modelo 3D.fbx, .objAula 13 (a mesma ideia do OBJ da Aula 07)
Áudio.wav, .mp3, .oggAula 14
Prefab.prefabAula 11

Todo asset tem um arquivo .meta ao lado, com o mesmo nome (MovimentoObjeto.cs.meta). Ele guarda as opções de importação e um identificador único, o GUID. É pelo GUID — e não pelo nome ou pelo caminho — que uma cena sabe qual script, material ou textura está usando. Consequência prática: mova, renomeie e apague assets pela janela Project, que leva o .meta junto. Mover um arquivo pelo Finder ou pelo Explorer sem o .meta gera um GUID novo, e toda referência a ele vira Missing no Inspector.

Cena é um asset (.unity) que descreve um "lugar" do jogo: a lista de GameObjects, a hierarquia entre eles e o valor de cada componente. Um jogo costuma ter várias — menu, fases, créditos — e o Editor mostra na Hierarchy a cena aberta no momento. O arquivo de cena guarda referências aos assets (o material da esfera, o script que a move), não cópias deles: o mesmo material pode ser usado por mil objetos em dez cenas. O projeto novo já vem com uma cena de exemplo, Assets/Scenes/SampleScene.

Pacote é um conjunto de funcionalidades da Unity ou de terceiros — pipeline de renderização, Input System, ferramentas de RV — instalado pelo Package Manager (Window → Package Management → Package Manager). O conteúdo dos pacotes aparece na pasta Packages da janela Project, só para leitura: é código e assets que você usa, mas não edita.

Ponte com o Módulo 1

No Módulo 1, "o projeto" era uma pasta com arquivos .py, e a cena era o que o seu paintGL desenhava — existia só enquanto o programa rodava. Na Unity, a cena é um arquivo de dados, editado no Editor e carregado pelo runtime; o código (os scripts) fica separado dela e é ligado aos objetos como componente.

Localizando-se na janela Project​

A janela Project é a biblioteca de conteúdo do projeto: mostra a pasta Assets/ (e a Packages/) como o Editor a enxerga.

  • Duas colunas. À esquerda, a árvore de pastas, com a seção Favorites no topo; à direita, o conteúdo da pasta selecionada, com miniaturas. Se ela aparecer em coluna única, mude em ⋮ → Two Column Layout. O controle deslizante no rodapé muda o tamanho das miniaturas; no extremo esquerdo, vira lista.
  • Trilha de navegação. Acima do conteúdo aparece o caminho da pasta atual (Assets > Aulas > Aula10); clique em qualquer trecho para voltar.
  • Busca com filtros. O campo de busca procura em todo o projeto. Filtros úteis: t:Material (por tipo), t:Scene, t:Script, l:rotulo (por rótulo) — esfera t:Material acha os materiais com "esfera" no nome. Os botões ao lado do campo montam esses filtros por clique (Search by Type, Search by Label). Uma busca pode ser salva nos Favorites.
  • Busca global. Ctrl/Cmd + K abre a janela Search, que procura ao mesmo tempo em assets, objetos da cena, menus e configurações.
  • De um objeto para o asset. No Inspector, clicar uma vez em um campo que referencia um asset (o material do Mesh Renderer, o script de um componente) destaca esse asset na janela Project.
  • Do asset para a cena. Botão direito sobre o asset → Find References In Scene filtra a Hierarchy para mostrar só os objetos que o usam.
  • Do Editor para o disco. Botão direito → Reveal in Finder (macOS) ou Show in Explorer (Windows) abre a pasta real do arquivo.
  • Criar. Botão direito sobre uma pasta → Create oferece pastas, cenas, materiais, scripts e os demais tipos de asset.

Nesta disciplina, cada aula guarda o que produz em Assets/Aulas/AulaNN/, com subpastas por tipo (Materials/, Scripts/). Organizar desde a primeira aula evita a pasta Assets/ virar um depósito de arquivos soltos.

A interface do Editor​

O Editor é dividido em janelas encaixáveis. Seis delas sustentam praticamente todo o trabalho desta aula:

  1. Scene — a cena em edição, navegável livremente. É a sua janela de trabalho; não é o que o jogador vê.
  2. Hierarchy — a lista de objetos da cena, em árvore. É o scene graph: arrastar um objeto para dentro de outro o torna filho, e o filho passa a herdar as transformações do pai.
  3. Project — os arquivos do projeto (a pasta Assets/): cenas, scripts, materiais, texturas, modelos, prefabs.
  4. Inspector — os componentes do objeto (ou o conteúdo do arquivo) selecionado, com os campos editáveis.
  5. Game — o que a câmera do jogo enxerga, com a proporção de tela escolhida. É o resultado, não o editor.
  6. Console — mensagens, avisos e erros, incluindo o que seus scripts escreverem com Debug.Log.
Janela do Editor da Unity. À esquerda, a Hierarchy lista Aula10 com Main Camera, Directional Light, Chao e Esfera, esta última selecionada. Ao centro, a Scene view mostra o plano cinza com a esfera azul e o gizmo de translação; ao lado dela, a aba Game. Abaixo, as abas Project, com as pastas de Assets, e Console. À direita, o Inspector exibe os componentes da esfera.
As seis janelas que sustentam o trabalho desta aula: Scene e Game ao centro, Hierarchy à esquerda, Project e Console embaixo, Inspector à direita.

A Figura 3 mostra o arranjo padrão com a cena da atividade já montada.

Navegação na Scene view (vale a pena decorar agora):

AçãoComo
Olhar em volta e voarbotão direito pressionado + mover o mouse; com o direito pressionado, W/A/S/D andam, Q/E descem e sobem, Shift acelera
Orbitar em torno do ponto focalAlt (Option no macOS) + botão esquerdo
Aproximar e afastarroda do mouse, ou Alt/Option + botão direito; no trackpad, deslizar com dois dedos
Arrastar a vistabotão do meio; ou a ferramenta View (Q) + botão esquerdo; no macOS, Option + Cmd + botão esquerdo
Enquadrar o objeto selecionadoF (Shift + F passa a segui-lo)

O gizmo de eixos no canto superior direito mostra a orientação atual. Clicar em um dos eixos alinha a vista a ele; clicar no rótulo abaixo do gizmo (Persp/Iso) alterna entre projeção perspectiva e ortográfica — a mesma distinção da Aula 05, agora como botão.

GameObject e Component: composição em vez de herança​

Um GameObject é um contêiner vazio com nome, camada e um Transform. Tudo o que ele faz vem dos Components anexados: Mesh Filter dá a geometria, Mesh Renderer o faz aparecer, Light o faz iluminar, Rigidbody o faz cair, e um script seu o faz se mexer.

Isso é composição: em vez de uma hierarquia de classes (Objeto → ObjetoVisível → ObjetoQueSeMove), o comportamento é montado juntando peças independentes. Vale a comparação com o Módulo 1: lá, um objeto era um par de listas (vértices e faces) mais o código que o desenhava; aqui, os mesmos dados estão em um asset de malha e o "código que desenha" é um componente configurável.

A hierarquia da janela Hierarchy é o grafo de cena: a matriz de um filho é composta com a do pai, exatamente como glPushMatrix/glPopMatrix compunham transformações aninhadas. Girar o pai gira os filhos em torno do pai.

Inspector da esfera, de cima para baixo: nome Esfera, componente Transform com Position 0, 0.5, 0, componente Sphere (Mesh Filter) com a malha Sphere, Sphere Collider, Mesh Renderer com as seções Lighting, Probes e Additional Settings, e o script Movimento Objeto com os campos Velocidade 5 e Velocidade Rotacao 60.
A esfera lida como lista de componentes: geometria, colisor, renderização e comportamento, cada um configurável por si.

Repare, na Figura 4, que o script aparece como mais um componente entre os outros — e que os campos marcados com [SerializeField] viraram campos editáveis, com o cabeçalho "Configurações de movimento" que o atributo [Header] criou.

Sistema de coordenadas: a Unity é de mão esquerda​

A Unity usa um sistema de mão esquerda, com +X+X para a direita, +Y+Y para cima e +Z+Z para frente — entrando na tela. O OpenGL do Módulo 1 usa um sistema de mão direita, em que +Z+Z sai da tela e a câmera padrão olha para −Z-Z. A Figura 5 compara os dois.

Dois sistemas de eixos lado a lado. À esquerda, OpenGL: X para a direita, Y para cima e Z saindo da tela na diagonal inferior esquerda, com uma seta de rotação positiva em torno de Y no sentido anti-horário visto de cima. À direita, Unity: X para a direita, Y para cima e Z entrando na tela na diagonal superior direita, com a seta de rotação positiva em torno de Y no sentido horário visto de cima.
Os eixos X e Y coincidem; o que muda é o sentido de Z — e, como consequência, o sentido positivo das rotações.

Duas consequências práticas:

  • Vector3.forward é (0,0,1)(0,0,1) e aponta para longe do observador. Em OpenGL, avançar para dentro da cena era caminhar no −Z-Z.
  • O sentido aparente das rotações positivas se inverte. Nos dois sistemas, uma rotação de +90°+90° em torno de YY leva o eixo ZZ sobre o eixo XX; como +Z+Z aponta para lados opostos, quem olha a cena de cima vê o giro positivo em sentido horário na Unity e anti-horário no OpenGL. É a diferença entre a regra da mão direita e a da mão esquerda.
Ponte com o Módulo 1

A regra da mão direita da Aula 05 continua válida — para o OpenGL. Aqui vale a regra da mão esquerda: polegar esquerdo no sentido positivo do eixo, os dedos indicam o sentido positivo do ângulo. Ao trazer um modelo ou uma conta feita em um sistema de mão direita, é o eixo Z (e o sinal dos ângulos) que precisa de atenção.

Transform: posição, rotação e escala​

Todo GameObject tem um Transform, e ele é exatamente a matriz de modelagem da Aula 06, guardada em três campos legíveis:

  • Position — um ponto (x,y,z)(x, y, z), em unidades da Unity (1 unidade = 1 metro, por convenção).
  • Rotation — exibida no Inspector como ângulos de Euler em graus, mas armazenada internamente como quatérnio.
  • Scale — fatores (Ex,Ey,Ez)(E_x, E_y, E_z) aplicados nos eixos locais.

Por que quatérnios. Ângulos de Euler são três rotações aplicadas em sequência em torno de eixos fixos. Quando duas dessas rotações alinham seus eixos, perde-se um grau de liberdade — o gimbal lock: girar em torno de dois eixos diferentes passa a produzir o mesmo movimento. Quatérnios representam a rotação como um eixo e um ângulo codificados em quatro números, não sofrem gimbal lock e interpolam suavemente entre orientações, o que é essencial em animação. O Inspector mostra Euler porque é legível para humanos; a engine converte para quatérnio ao aplicar.

Local e mundo. transform.localPosition é a posição em relação ao pai; transform.position é a posição no mundo. O mesmo vale para rotação e para a escala (localScale, e a lossyScale resultante quando há escalas acumuladas na hierarquia). Escala não uniforme em cadeia com rotações produz deformações — o mesmo alerta da Aula 04, quando vimos que rotação e escala só comutam quando a escala é uniforme.

A ordem importa, como sempre

transform.Translate e transform.Rotate compõem transformações sobre o estado atual, como as chamadas OpenGL faziam. Transladar e depois girar não é o mesmo que girar e depois transladar — e é isso que faz a esfera da atividade andar em círculo, como você vai ver adiante.

Anatomia da renderização: Mesh, Material e Shader​

ComponenteO que guardaCorrespondente no Módulo 1
Mesh Filterreferência à malha: vértices, triângulos (índices), normais, coordenadas de texturaa malha indexada da Aula 07 (VERTICES + FACES)
Mesh Renderersubmete a malha ao pipeline, com os materiais e as opções de sombrao seu laço de desenho, glDrawElements e o descarte de faces
Material (asset)valores que alimentam o shader: cor base, metalicidade, rugosidade, mapasglMaterialfv e as texturas da Aula 09
Shadero programa que roda na GPU e decide a cor de cada fragmentoo pipeline fixo de iluminação do OpenGL 2.1

No URP, o shader padrão é o Universal Render Pipeline/Lit. Os campos que você mais usa nele:

  • Base Map — a cor base (albedo) e, opcionalmente, uma textura. É o que os tutoriais antigos chamam de Albedo.
  • Metallic Map — sem textura, vira um controle deslizante de 0 (dielétrico: madeira, plástico, concreto) a 1 (metal).
  • Smoothness — logo abaixo, de 0 (fosco, reflexo espalhado) a 1 (espelhado). É o primo moderno do expoente especular da Aula 08.
  • Normal Map — perturba as normais para simular relevo sem acrescentar geometria (o bump mapping citado na Aula 09).

Câmera e projeções​

O componente Camera é a câmera sintética da Aula 05 com outros nomes. A Figura 6 mostra o volume de visualização em perspectiva e a correspondência entre os parâmetros.

Vista lateral do volume de visualização: a partir da câmera saem duas retas que definem o campo de visão vertical; um plano near próximo e um plano far distante delimitam o tronco de pirâmide. Um objeto dentro do tronco é marcado como visível; um antes do near e outro depois do far são marcados como recortados. Ao lado, uma tabela relaciona fovy, aspect, near e far de gluPerspective aos campos Field of View e Clipping Planes do componente Camera.
O que estava nos argumentos de gluPerspective agora está em campos do Inspector — a geometria é a mesma.
CampoSignificadoValor padrão
ProjectionPerspective ou OrthographicPerspective
Field of Viewabertura vertical em graus (o fovy)60
Clipping Planes → Neardistância do plano de recorte próximo0,3
Clipping Planes → Fardistância do plano de recorte distante1000
Background Typeo que aparece onde não há geometria: céu, cor sólida ou nadaSkybox

A proporção (aspect) não é um campo: vem da proporção da janela Game, que pode ser fixada em resoluções específicas pelo seletor no topo dela.

Near pequeno demais custa precisão

O buffer de profundidade da Aula 07 distribui precisão de forma não linear: quase toda ela fica perto do plano near. Reduzir o near de 0,3 para 0,01 "para ver objetos coladinhos" faz objetos distantes competirem pelos mesmos valores de profundidade e produz o cintilar conhecido como z-fighting. Prefira ajustar a cena.

C# para quem vem de Python​

O Módulo 1 foi escrito em Python. C# é estaticamente tipada e compilada, mas a distância é menor do que parece:

Python (Módulo 1)C# (Unity)
velocidade = 5.0float velocidade = 5.0f; (o f marca float, não double)
blocos por indentaçãoblocos por { }; fim de instrução com ;
def atualizar(self):void Update()
print(x)Debug.Log(x);
lista = []List<int> lista = new List<int>(); (exige using System.Collections.Generic;) ou int[] vetor = new int[8];
# comentário// comentário
import mathusing UnityEngine; (traz o namespace, não um módulo)
self.postransform.position (o componente é acessível direto)
f-string f"{a}"interpolação $"{a}"

Um script de comportamento herda de MonoBehaviour e é anexado a um GameObject. A engine chama seus métodos em momentos definidos:

MétodoQuando rodaPara quê
Awake()ao criar o objeto, antes de tudopreparar referências internas
OnEnable()toda vez que o componente é ativadoassinar eventos
Start()antes do primeiro Update, com todos os objetos já criadosinicialização que depende de outros objetos
Update()uma vez por quadroentrada, lógica, movimento não físico
FixedUpdate()em intervalos fixos (padrão: 50 Hz)física, forças, Rigidbody
LateUpdate()depois de todos os Updatecâmera que segue o personagem
OnDestroy()ao destruir o objetolimpeza

Time.deltaTime não é detalhe. Update roda uma vez por quadro, e a taxa de quadros varia com a máquina e com a cena. Somar 0,1 por quadro dá 6 unidades por segundo a 60 quadros por segundo e 3 a 30 — o mesmo programa, velocidades diferentes. Multiplicar pelo tempo decorrido desde o quadro anterior (Time.deltaTime) converte "por quadro" em "por segundo", e o movimento passa a ser o mesmo em qualquer máquina.

O primeiro script​

📥 Baixe o arquivo: MovimentoObjeto.cs

MovimentoObjeto.cs
using UnityEngine;

namespace Aula10
{
public class MovimentoObjeto : MonoBehaviour
{
[Header("Configurações de movimento")]
[Tooltip("Unidades por segundo ao longo do eixo Z local (frente).")]
[SerializeField] private float velocidade = 5.0f;

[Tooltip("Graus por segundo em torno do eixo Y (cima).")]
[SerializeField] private float velocidadeRotacao = 60.0f;

[SerializeField] private bool moverNoEspacoDoMundo = false;

private void Start()
{
Debug.Log($"Script inicializado no objeto: {gameObject.name}");
}

private void Update()
{
// P_final = P_inicial + (direção * velocidade * deltaTime)
Vector3 deslocamento = Vector3.forward * (velocidade * Time.deltaTime);
transform.Translate(deslocamento, moverNoEspacoDoMundo ? Space.World : Space.Self);

// Rotação contínua em torno do eixo Y (cima).
transform.Rotate(Vector3.up * (velocidadeRotacao * Time.deltaTime));
}
}
}

Quatro detalhes que não são estéticos:

  • namespace Aula10 cumpre o papel do módulo em Python: agrupa os nomes da aula e evita que duas aulas do mesmo projeto disputem o nome MovimentoObjeto. Um MonoBehaviour dentro de um namespace aparece normalmente em Add Component.
  • [SerializeField] private expõe o campo no Inspector sem torná-lo público para outros scripts. [Header] e [Tooltip] documentam o campo para quem for ajustá-lo — inclusive você, duas semanas depois.
  • O valor do Inspector vence o valor do código. Depois que o componente existe no objeto, mudar o 5.0f no arquivo não muda a cena: o valor foi serializado. Ajuste pelo Inspector, ou use o menu de contexto do componente para redefinir.
  • Space.Self é o padrão de Translate. O deslocamento acontece nos eixos locais, que giram junto com o objeto — é por isso que um objeto que anda e gira ao mesmo tempo descreve um círculo.
Quatro erros de estreante
  1. Nome da classe diferente do nome do arquivo. MovimentoObjeto.cs precisa conter class MovimentoObjeto. Se divergirem, o componente não aparece em Add Component e o Console acusa.
  2. Esquecer Time.deltaTime. O movimento passa a depender da máquina.
  3. Editar durante o Play. Mudanças feitas no Inspector com o jogo rodando são descartadas ao parar. Pare primeiro.
  4. Esquecer de salvar a cena (Ctrl/Cmd + S). O script está salvo, a cena não — e o objeto volta sem o componente.

Atividades de Laboratório​

As três atividades usam a mesma cena, em sequência: a Atividade 1 a monta, a 2 põe a esfera sob o controle do teclado e a 3 acrescenta um cubo em órbita.

Atividade 1 — A primeira cena​

Monte a cena do zero. Os valores abaixo são os mesmos da cena de referência da disciplina, para que o resultado possa ser comparado.

0. Cena nova

  • Na janela Project, crie a pasta Aulas dentro de Assets e, dentro dela, a pasta Aula10 (botão direito → Create → Folder).
  • File → New Scene, escolha o modelo Basic (URP) e clique em Create. Ele traz só uma Main Camera e uma Directional Light — a SampleScene do template tem objetos que esta atividade não usa.
  • File → Save As, salve como Assets/Aulas/Aula10/Aula10.unity.

1. Cenário básico

  • GameObject → 3D Object → Plane, renomeado para Chao, em Position (0, 0, 0). O plano tem 10 × 10 unidades.
  • GameObject → 3D Object → Sphere, renomeada para Esfera, em Position (0, 0.5, 0). A esfera tem diâmetro 1, então 0,5 a coloca exatamente sobre o chão.

2. Materiais

  • Crie a pasta Assets/Aulas/Aula10/Materials.
  • Dentro dela, Create → Material (botão direito na janela Project, ou Assets → Create → Material) duas vezes. O material novo já usa o shader Universal Render Pipeline/Lit.
    • M_Chao: Base Map cinza #9E9E9E, Metallic Map 0, Smoothness 0.25.
    • M_EsferaAzul: Base Map azul #2659D9, Metallic Map 0.75, Smoothness 0.65.
  • Para mudar a cor, clique no retângulo ao lado de Base Map e digite o valor no campo Hexadecimal do seletor.
  • Arraste cada material sobre o objeto correspondente na Scene view.

3. Iluminação

  • Selecione a Directional Light e confira a rotação (50, −30, 0) e Shadow Type Soft Shadows — são os valores que o modelo Basic (URP) já cria. Gire a luz pelo Inspector e observe a sombra da esfera mudar de direção e comprimento enquanto ela gira: a direção da sombra vem só da rotação, não da posição. Volte a (50, −30, 0) antes de seguir.

4. Câmera

  • Selecione a Main Camera, que o modelo cria em (0, 1, −10), e ajuste Position (0, 2.5, −6) e Rotation (15, 0, 0). Mantenha Field of View 60 e Clipping Planes 0,3 e 1000. Confira o enquadramento na janela Game.

5. Script

  • Crie a pasta Assets/Aulas/Aula10/Scripts e, dentro dela, um script pelo menu de contexto da janela Project: Create → Scripting → MonoBehaviour Script (em versões mais antigas e em tutoriais, Create → C# Script). Digite o nome MovimentoObjeto antes de confirmar: o nome da classe gerada vem do nome digitado nesse momento.
  • Abra o script (clique duplo), substitua todo o conteúdo pelo código da seção anterior, salve e volte ao Editor. A compilação acontece ao recuperar o foco; confira no Console que não há erros.
  • Selecione a Esfera, clique em Add Component e escolha Movimento Objeto.
  • Ajuste velocidade e velocidadeRotacao pelo Inspector.

6. Execução

  • Salve a cena (Ctrl/Cmd + S) e pressione Play (Ctrl/Cmd + P). A esfera avança e gira ao mesmo tempo. Parado, o enquadramento deve ser o da Figura 7.
Renderização da cena: um plano cinza claro sobre fundo de céu, com uma esfera azul metálica apoiada no centro e sua sombra projetada à esquerda.
A cena montada nos valores acima, vista pela câmera do jogo.
Observe antes de seguir

Enquanto a esfera anda, ela não segue uma reta: descreve um círculo. Como Translate usa os eixos locais e a rotação gira esses eixos a cada quadro, a direção "frente" muda continuamente. Marque moverNoEspacoDoMundo no Inspector e compare: a trajetória vira uma reta, e o giro passa a ser só giro. Essa diferença é a resposta da primeira questão dissertativa.


Atividade 2 — Mover a esfera com o teclado​

Objetivo. Controlar a esfera com W, A, S, D ou com as setas, com a mesma velocidade em qualquer direção — inclusive na diagonal — e em qualquer máquina.

Ponto de partida. A cena da Atividade 1 e o esqueleto do script, com o laço de leitura do teclado já montado e três lacunas marcadas TODO.

📥 Baixe o arquivo-base: MovimentoPorTeclado.cs

MovimentoPorTeclado.cs (esqueleto)
using UnityEngine;
using UnityEngine.InputSystem;

namespace Aula10
{
public class MovimentoPorTeclado : MonoBehaviour
{
[Tooltip("Unidades por segundo.")]
[SerializeField] private float velocidade = 5.0f;

private void Update()
{
Keyboard teclado = Keyboard.current;
if (teclado == null) return; // nenhum teclado conectado

float horizontal = 0f; // -1 = esquerda (A, seta esquerda); +1 = direita (D, seta direita)
float vertical = 0f; // -1 = trás (S, seta para baixo); +1 = frente (W, seta para cima)

// TODO 1: some ou subtraia 1 em horizontal e vertical conforme as teclas pressionadas.
// Exemplo, para a tecla A: if (teclado.aKey.isPressed) horizontal -= 1f;

// TODO 2: monte a direção no plano XZ e normalize-a quando a diagonal for pressionada.

// TODO 3: desloque o objeto no espaço do MUNDO, em unidades por segundo.
}
}
}
O Input Manager legado não funciona aqui

Tutoriais antigos resolvem esta atividade com Input.GetAxis("Horizontal"), do Input Manager legado. No template da 6.3 esse caminho está desligado (Active Input Handling = Input System Package) e a chamada lança InvalidOperationException a cada quadro — é o erro mais comum ao seguir material desatualizado. Esta atividade lê o teclado pelo Input System, direto do dispositivo; a Aula 11 mostra a forma com Input Actions.

Roteiro​

Passo 1 — Prepare a cena. Abra Aula10.unity e salve uma cópia em File → Save As como Assets/Aulas/Aula10/Aula10-Pratica.unity. Selecione a Esfera e desmarque a caixa ao lado do nome do componente Movimento Objeto no Inspector: o componente continua no objeto, mas deixa de rodar. Assim a esfera fica parada, esperando o teclado.

Passo 2 — Traga o script para o projeto. Arraste o arquivo baixado da pasta do seu computador para Assets/Aulas/Aula10/Scripts na janela Project — a Unity importa e compila ao soltar. (Alternativa: Create → Scripting → MonoBehaviour Script com o nome MovimentoPorTeclado e cole o esqueleto.) Selecione a Esfera, Add Component e escolha Movimento Por Teclado. Confira o Console: o esqueleto compila sem erros e, por enquanto, não faz nada.

Passo 3 — Leia as teclas (TODO 1). O Keyboard do Input System tem uma propriedade por tecla: teclado.aKey, dKey, wKey, sKey, leftArrowKey, rightArrowKey, upArrowKey, downArrowKey. Cada uma responde isPressed (tecla presa neste quadro). Escreva quatro if, um por sentido, aceitando a letra ou a seta. Para conferir antes de mover qualquer coisa, acrescente temporariamente Debug.Log($"{horizontal}, {vertical}"); no fim do Update, dê Play, clique na janela Game — o teclado só chega ao jogo quando ela tem o foco — e pressione as teclas: o Console deve mostrar valores entre −1 e 1. Apague o Debug.Log depois.

Passo 4 — Monte a direção (TODO 2). Crie Vector3 direcao = new Vector3(horizontal, 0f, vertical);. O eixo vertical do teclado vira o eixo ZZ da cena, porque o chão é o plano XZXZ e +Z+Z aponta para frente (mão esquerda). Com W e D juntos, a direção é (1,0,1)(1, 0, 1), de comprimento 2≈1,41\sqrt{2} \approx 1{,}41: sem correção, a diagonal anda 41% mais rápido. Normalize só nesse caso: if (direcao.sqrMagnitude > 1f) direcao.Normalize();.

Passo 5 — Mova (TODO 3). Use transform.Translate com a direção multiplicada por velocidade * Time.deltaTime e o espaço Space.World. O espaço do mundo garante que W leve sempre para longe da câmera, qualquer que seja a orientação da esfera.

Passo 6 — Teste. Dê Play, clique na janela Game e dirija a esfera. W a afasta da câmera (+Z+Z), D a leva para a direita (+X+X). Ajuste velocidade no Inspector durante o Play e observe o efeito imediato — lembrando que o valor volta ao parar.

Checklist de conclusão​

  • W/A/S/D e as setas movem a esfera nos quatro sentidos.
  • Na diagonal, a esfera anda com a mesma velocidade que nos eixos.
  • O deslocamento usa Time.deltaTime e Space.World.
  • O Debug.Log de teste do Passo 3 foi removido.
  • O Console não mostra erros nem avisos.

Para responder​

  1. Por que sqrMagnitude > 1f, e não magnitude > 1f? O resultado muda?
  2. Reative o Movimento Objeto da esfera (os dois scripts juntos). A esfera gira e anda em círculo; o teclado continua levando W para longe da câmera? E se você trocar Space.World por Space.Self no seu script?
  3. De propósito, troque a leitura de uma tecla por Input.GetAxis("Horizontal"), dê Play e copie a primeira linha do erro no Console. Depois desfaça. O que a mensagem diz sobre a configuração do projeto?

Atividade 3 — Um cubo em órbita​

Objetivo. Fazer um cubo orbitar a esfera, a uma velocidade angular definida no Inspector, e manter o raio da órbita mesmo quando a esfera se move.

Ponto de partida. A cena da Atividade 2, com a esfera controlada pelo teclado, e o esqueleto do script de órbita.

📥 Baixe o arquivo-base: OrbitaAoRedor.cs

OrbitaAoRedor.cs (esqueleto)
using UnityEngine;

namespace Aula10
{
public class OrbitaAoRedor : MonoBehaviour
{
[Tooltip("Objeto em torno do qual orbitar (arraste a esfera aqui).")]
[SerializeField] private Transform centro;

[Tooltip("Graus por segundo da órbita.")]
[SerializeField] private float velocidadeOrbita = 45.0f;

private void Update()
{
// TODO 1: se nenhum centro foi definido no Inspector, não faça nada.

// TODO 2: gire em torno da posição do centro, no eixo vertical do mundo,
// velocidadeOrbita graus por segundo (transform.RotateAround).
}
}
}

transform.RotateAround(ponto, eixo, angulo) gira o objeto em torno de uma reta que passa por ponto na direção eixo. É a composição translação → rotação → translação inversa que a Aula 04 deduziu para girar em torno de um ponto arbitrário, agora em três dimensões: M=T(ponto) Reixo(angulo) T(−ponto)M = T(\text{ponto})\,R_{\text{eixo}}(\text{angulo})\,T(-\text{ponto}).

Roteiro​

Passo 1 — Crie o cubo. GameObject → 3D Object → Cube, renomeado para Cubo, com Position (2, 0.5, 0) e Scale (0.5, 0.5, 0.5). Crie o material M_CuboAmbar (Base Map #D98C1A, Metallic Map 0, Smoothness 0.35) e arraste-o sobre o cubo.

Passo 2 — Traga o script. Importe OrbitaAoRedor.cs para Assets/Aulas/Aula10/Scripts, como na Atividade 2, e adicione o componente ao Cubo. Arraste a Esfera da Hierarchy para o campo Centro do componente.

Passo 3 — Complete o Update (TODOs 1 e 2). O teste de centro == null evita um erro a cada quadro quando o campo fica vazio. A chamada de órbita usa centro.position, Vector3.up e o ângulo deste quadro: graus por segundo vezes Time.deltaTime.

Passo 4 — Preveja e confira. Antes do Play, calcule o raio da órbita (distância inicial entre o cubo e a esfera) e o tempo de uma volta com 45°/s. Dê Play e cronometre algumas voltas. Observe também a face do cubo voltada para a esfera: ela muda?

Passo 5 — Mova a esfera durante a órbita. Com o Play rodando, dirija a esfera com o teclado por alguns segundos e observe a distância entre os dois. O raio se mantém?

Passo 6 — Corrija com a hierarquia. Pare o Play. Na Hierarchy, arraste o Cubo para dentro da Esfera, tornando-o filho dela. Dê Play e repita o Passo 5. Agora o cubo acompanha a esfera sem perder o raio: o filho herda a translação do pai — o mesmo efeito de desenhar o cubo entre um glPushMatrix e um glPopMatrix depois de transladar para a esfera.

Checklist de conclusão​

  • O cubo orbita a esfera a 45°/s, no plano do chão.
  • Com o campo Centro vazio, o Play não gera erros no Console.
  • Com o cubo filho da esfera, o raio da órbita não muda quando a esfera anda.
  • A cena Aula10-Pratica.unity foi salva.

Para responder​

  1. Qual o raio da órbita e o período de uma volta? Em que sentido o cubo gira, visto de cima, e por quê?
  2. Por que o raio mudava no Passo 5, se RotateAround preserva distâncias?
  3. No Passo 6, o que aconteceria com o cubo se o Movimento Objeto da esfera estivesse ativo, fazendo-a girar em torno de si? Teste e explique com a hierarquia.

Exercícios (checkpoints)​

Questões dissertativas​

Q

O Pygame é uma game engine? Responda usando a distinção entre biblioteca, framework e engine e o conceito de inversão de controle.

Q

Descreva as etapas do laço de jogo e explique por que as engines avançam a física em passos de tempo fixos, enquanto a lógica usa o tempo variável de cada quadro.

Q

Três colegas vão começar projetos: (a) um protótipo 2D para testar uma mecânica em uma tarde; (b) um jogo 2.5D para celular com um modo em realidade aumentada; (c) um passeio fotorrealista por um edifício, apresentado em máquinas com GPU potente. Qual ferramenta — Unity, Unreal Engine ou Pygame — você recomendaria a cada um, e por quê?

Q

Qual a diferença entre os eixos locais (Local Space) e os eixos globais (World Space) de um GameObject, e como isso muda o resultado de transform.Translate?

Q

O que acontece com a movimentação de um objeto se omitirmos a multiplicação por Time.deltaTime em Update?

Q

Por que a Unity armazena rotações como quatérnios se o Inspector mostra ângulos de Euler?

Questões objetivas​

Quiz9 questões

1. O que distingue uma game engine (ou um framework) de uma biblioteca como o Pygame?

  • a)A biblioteca desenha mais rápido que a engine
  • b)A engine controla o laço principal e chama o código do jogo em pontos definidos
  • c)A engine só funciona com gráficos 3D
  • d)A biblioteca não pode ser usada para fazer jogos
  • e)A engine dispensa qualquer programação

2. Por que as engines avançam a simulação física em passos de tempo fixos?

  • a)Para economizar memória de vídeo
  • b)Porque a GPU só aceita intervalos fixos
  • c)Porque passos variáveis e longos tornam a simulação instável, e objetos rápidos podem atravessar colisores
  • d)Para sincronizar o áudio com a imagem
  • e)Porque o Editor não consegue exibir passos variáveis

3. Em que linguagens se escreve a lógica de jogo na Unreal Engine 5?

  • a)C#
  • b)Python, por meio do Pygame
  • c)Lua
  • d)C++ e Blueprints, um sistema de programação visual
  • e)Java

4. Um colega moveu um material de pasta pelo Finder (ou Explorer), sem levar o arquivo .meta, e a esfera da cena perdeu o material. Por quê?

  • a)O Finder corrompe arquivos .mat
  • b)Materiais só podem ficar na pasta Materials
  • c)A cena guarda uma cópia do material, que ficou desatualizada
  • d)A Unity só aceita um material por projeto
  • e)A cena referencia o material pelo GUID gravado no .meta; sem ele, a Unity gera um GUID novo e a referência se perde

5. Na Unity, o que define o comportamento de um GameObject?

  • a)Os componentes anexados a ele
  • b)A classe da qual ele herda
  • c)A posição dele na Hierarchy
  • d)O material do Mesh Renderer
  • e)A cena em que ele está

6. No sistema de coordenadas da Unity, para onde aponta Vector3.forward, isto é, (0, 0, 1)?

  • a)Para dentro da tela, afastando-se do observador
  • b)Para fora da tela, na direção do observador
  • c)Para cima
  • d)Para a direita
  • e)Depende da rotação da câmera

7. Qual o efeito de multiplicar o deslocamento por Time.deltaTime dentro de Update?

  • a)Torna a velocidade independente da taxa de quadros
  • b)Aumenta a taxa de quadros
  • c)Suaviza a rotação com quatérnios
  • d)Ativa a física do objeto
  • e)Converte espaço local em espaço do mundo

8. O campo Field of View do componente Camera corresponde a qual argumento de gluPerspective?

  • a)fovy, a abertura vertical
  • b)aspect, a proporção
  • c)near, o plano próximo
  • d)far, o plano distante
  • e)A posição do observador

9. Qual componente guarda a malha (vértices e triângulos) de um objeto 3D?

  • a)Mesh Filter
  • b)Mesh Renderer
  • c)Transform
  • d)Material
  • e)Light

Referências​

Principais (essenciais)​

Aprofundamento (opcionais)​