Cutscene na Unity com Timeline e Cinemachine

Unity Timeline na prática: cutscene de 20 segundos com animação, áudio, cortes de câmera no Cinemachine Track e Signals para devolver o controle ao jogador.
Cutscene na Unity com Timeline e Cinemachine
A Unity Timeline é o editor de sequências da Unity: uma linha do tempo onde você coloca animações, ativação de objetos, áudio e cortes de câmera em faixas paralelas, e um componente Playable Director toca tudo sincronizado. Para uma cutscene, você cria um Timeline asset, liga o personagem a uma faixa de animação, a Main Camera a uma faixa do Cinemachine e usa Signals para avisar o gameplay quando a cena termina.
Aqui você monta uma cutscene curta, de uns 20 segundos: o portão se abre, a câmera corta para o rosto do personagem, toca um som, a câmera volta e o controle retorna ao jogador. Inclui o script para iniciar e pular a cutscene e a correção dos dois bugs que todo mundo encontra na primeira vez. Tudo no Unity 6.3 LTS com Cinemachine 3.
O que é a Timeline da Unity e quando usar
A Timeline resolve um problema específico: coisas que acontecem em momentos exatos, coordenadas entre vários objetos. Exemplos:
- Cutscene de abertura, de chefe, de fim de fase.
- Porta que abre com câmera mostrando a sala do outro lado.
- Sequência de tutorial com câmera guiando o olhar.
- Trailer gravado dentro do jogo.
Ela não serve para lógica que depende do jogador (inimigo que reage, combate). Para isso existe o Animator e o seu código. Uma boa regra: se a sequência é igual toda vez que roda, é Timeline; se ela depende de decisões em tempo de jogo, é código.
O pacote com.unity.timeline vem instalado com o Editor, então não precisa de Package Manager. A documentação atual é a da linha 1.8. Para os cortes de câmera, instale o Cinemachine pelo Package Manager.
Antes de abrir a ferramenta, vale ter a cena escrita: quem aparece, o que acontece, quanto tempo dura cada plano. O post sobre narrativa em jogos ajuda a decidir o que merece virar cutscene e o que deve ficar na jogabilidade.
Criando o Playable Director e o primeiro Timeline asset
- Na cena, crie um GameObject vazio chamado
Cutscene_Portao. - Abra Window > Sequencing > Timeline.
- Com o
Cutscene_Portaoselecionado, a janela mostra o botão Create. Clique, salve comoPortao.playablenuma pastaAssets/Timelines.
A Unity adiciona ao objeto um Playable Director, que é o "tocador", e cria o asset .playable, que é a "partitura". O mesmo asset pode ser tocado por directors diferentes, cada um ligando as faixas a objetos da sua cena.
No Inspector do Playable Director, os campos que importam agora:
- Playable: o Timeline asset.
- Update Method: Game Time (padrão, respeita
Time.timeScale), Unscaled Game Time (ignora pausa e câmera lenta), DSP Clock (sincronizado com o áudio) ou Manual. - Play On Awake: desmarque. A cutscene vai começar por script, quando o jogador entrar na área.
- Wrap Mode: Hold (segura o último frame), Loop (repete) ou None (toca uma vez e para). Vamos voltar a ele nos erros comuns.
- Bindings: a lista de quem cada faixa controla.
Trilhas de animação, ativação e áudio
No canto da janela Timeline, o botão + (Add) mostra os tipos de faixa. Para a cutscene:
Activation Track: liga e desliga um objeto. Arraste o objeto FX_PoeiraPortao para a faixa. O bloco "Active" define o intervalo em que ele existe. Use para partículas, luzes, objetos de cenário que aparecem. Na faixa, Post-playback State decide como o objeto fica quando a Timeline termina: Active, Inactive, Revert ou Leave As Is.
Animation Track: anima um objeto com Animator. Arraste o portão para a faixa (a Unity pergunta se pode adicionar um Animator, aceite). Você tem dois jeitos de criar o movimento:
- Arrastar um Animation Clip pronto para a faixa.
- Clicar no botão de gravação vermelho da faixa, mover o tempo, mexer no objeto na cena e deixar a Unity gravar keyframes. Ao sair da gravação, o resultado vira um Infinite Clip na faixa, que você pode converter em clip normal pelo menu da faixa (Convert To Clip Track).
Para o personagem, arraste o objeto com o Animator dele e coloque um clip de "olhar para o portão" no momento certo. Sobrepor dois clips na mesma faixa cria um blend entre eles.
Um ajuste que evita metade das dores de cabeça: no Inspector da Animation Track, Track Offsets. Apply Scene Offsets faz o clip partir da posição atual do personagem na cena; sem isso, um clip com movimento de raiz pode teletransportar o personagem para a origem do mundo.
Audio Track: arraste um AudioClip (o rangido do portão). Ligue a faixa a um AudioSource da cena nos Bindings para controlar volume e espacialização. Ajuste o início do som arrastando o bloco até casar com o movimento do portão.
Se você trabalha com animadores, a Timeline é a ponte entre o clip deles e o momento certo no jogo. O post sobre o que faz um animador de jogos mostra esse lado do pipeline.
Cortes de câmera com Cinemachine Track
Crie duas CinemachineCameras na cena:
CM_Portao: enquadra o portão abrindo.CM_Rosto: close no personagem.
Deixe as duas com prioridade baixa, para não roubar a câmera do jogo fora da cutscene.
Na Timeline, + > Cinemachine Track. Arraste a Main Camera (a que tem o Cinemachine Brain) para o binding da faixa. Agora clique com o botão direito na faixa e adicione Cinemachine Shot clips. Cada clip aponta para uma CinemachineCamera, no campo da câmera no Inspector do clip.
A estrutura da cutscene de 20 segundos:
| Tempo | Câmera | O que acontece |
|---|---|---|
| 0 a 6 s | CM_Portao | portão abre, poeira, rangido |
| 6 a 12 s | CM_Rosto | personagem reage |
| 12 a 18 s | CM_Portao | revela o caminho |
| 18 a 20 s | câmera do jogo | volta ao gameplay |
Clips encostados fazem corte seco. Clips sobrepostos fazem blend pelo tempo da sobreposição. Para voltar suave para a câmera de gameplay no fim, use Ease Out Duration no último clip: enquanto a Timeline comanda o Cinemachine, ela passa por cima da escolha por prioridade do Brain, e quando a faixa termina, o Brain volta a mandar.
Até aqui, você tem uma cena bonita que toca sozinha. O problema real começa quando ela precisa conversar com o resto do jogo: travar o jogador, salvar que a cena já foi vista, não tocar de novo, deixar pular. É esse encaixe entre sistemas que separa uma demonstração de um jogo, e é o tipo de coisa que um curso de Unity com projeto completo trabalha do começo ao fim.
Signals: chamar código no momento certo da cutscene
Signals são marcadores na Timeline que disparam funções de script. Eles têm três peças:
- Signal asset: um "nome de evento" salvo no projeto, por exemplo
FimDaCutscene. Crie por Assets > Create > Timeline > Signal, ou direto pelo Inspector do marcador. - Signal Emitter: o marcador na linha do tempo. Adicione uma Signal Track (+ > Signal Track) ligada ao objeto que vai reagir, posicione o tempo em 20 s, clique com o botão direito na faixa e escolha Add Signal Emitter. No Inspector do marcador, escolha o Signal asset.
- Signal Receiver: componente no objeto ligado à faixa. Com o marcador selecionado, clique em Add Signal Receiver. Na lista de reações, escolha o Signal e a função, como num botão de UI.
Para o nosso caso, ligue a Signal Track ao objeto Cutscene_Portao e faça o FimDaCutscene chamar CutsceneController.EndCutscene(), do script abaixo. No marcador há duas opções: Retroactive (dispara mesmo se a Timeline começar depois do tempo do marcador) e Emit Once (dispara só na primeira volta, útil com Loop).
Iniciar e pular a cutscene por script com PlayableDirector
Arquivo CutsceneController.cs, no Cutscene_Portao, junto com um BoxCollider2D ou BoxCollider marcado como trigger (aqui, versão 3D):
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Playables;
[RequireComponent(typeof(PlayableDirector))]
public class CutsceneController : MonoBehaviour
{
[SerializeField] private PlayableDirector director;
[SerializeField] private MonoBehaviour playerController;
[SerializeField] private InputAction skipAction = new InputAction("Skip", InputActionType.Button, "<Keyboard>/escape");
[SerializeField] private string playerTag = "Player";
private bool hasPlayed = false;
private bool isPlaying = false;
private void Reset()
{
director = GetComponent<PlayableDirector>();
}
private void OnEnable()
{
skipAction.Enable();
skipAction.performed += OnSkip;
}
private void OnDisable()
{
skipAction.performed -= OnSkip;
skipAction.Disable();
}
private void OnTriggerEnter(Collider other)
{
if (hasPlayed || !other.CompareTag(playerTag))
{
return;
}
StartCutscene();
}
public void StartCutscene()
{
hasPlayed = true;
isPlaying = true;
playerController.enabled = false;
director.Play();
}
private void OnSkip(InputAction.CallbackContext context)
{
if (!isPlaying)
{
return;
}
director.time = director.duration;
director.Evaluate();
director.Stop();
EndCutscene();
}
public void EndCutscene()
{
if (!isPlaying)
{
return;
}
isPlaying = false;
playerController.enabled = true;
}
}
Como funciona:
playerControlleré o script de movimento do jogador. Desligá-lo trava o controle durante a cena.- A
InputActiondeclarada no próprio script já vem ligada ao Esc; no Inspector você pode adicionar o botão Start do gamepad. - Para pular, o código leva o tempo ao fim, chama
Evaluate()para aplicar o estado final e para o director. OStop()encerra a Timeline do mesmo jeito que o fim normal, então vale a regra do Wrap Mode explicada nos erros comuns: o que precisa continuar como no último frame (portão aberto, personagem no lugar novo) fica garantido noEndCutscene(). Ele é chamado diretamente, porque o Signal no fim da Timeline não dispara quando você salta o tempo. - O
isPlayingevita queEndCutscenerode duas vezes (uma pelo Signal, outra pelo pulo).
Se precisar saber quando a Timeline terminou sem Signal, o PlayableDirector tem o evento stopped, que recebe o próprio director como parâmetro.
Erros comuns: personagem voltando à pose inicial e cutscene que não toca
O personagem volta à pose inicial no fim. Com Wrap Mode None, a Timeline para e devolve as propriedades ao estado anterior. Com Hold, ela segura o último frame, mas o director continua mandando no Animator, e o gameplay não consegue animar o personagem. A solução prática: termine a cutscene com o personagem numa pose que o Animator de gameplay também tem (Idle), deixe em None e, se a posição mudou, mova o personagem por código no EndCutscene para onde ele terminou.
O personagem teletransporta para a origem do mundo. Track Offsets da Animation Track. Use Apply Scene Offsets ou Apply Transform Offsets.
A cutscene não toca. Confira: o Playable Director tem o asset no campo Playable; os Bindings não estão vazios (faixa sem binding fica sem efeito); o trigger está funcionando (o jogador precisa de Rigidbody ou CharacterController para disparar OnTriggerEnter); você não está chamando Play() antes de o objeto estar ativo.
A câmera não corta. A Cinemachine Track está sem a Main Camera no binding, ou os clips apontam para CinemachineCameras desativadas.
A cutscene roda durante o menu de pausa. Update Method em Unscaled Game Time. Se a pausa deve congelar a cutscene, use Game Time.
Próximo passo
Monte a cutscene do portão numa cena de teste com objetos simples (cubos e cápsulas servem) antes de usar a arte final. Quando funcionar, adicione um segundo Signal no meio da cena para tocar uma fala, e salve em PlayerPrefs que a cutscene já foi vista, para ela não repetir ao carregar a fase. O guia de Cinemachine na Unity aprofunda as câmeras que você usou nos cortes.
Perguntas frequentes
Preciso instalar a Timeline na Unity 6?
Não. O pacote Timeline (com.unity.timeline) vem instalado com o Editor. Para abrir a janela, use Window > Sequencing > Timeline. Para cortes de câmera com Cinemachine Track, aí sim você precisa instalar o pacote Cinemachine.
Por que meu personagem volta para a pose inicial quando a cutscene acaba?
Com Wrap Mode em None, o Playable Director para no fim e as propriedades animadas voltam ao que eram antes. Em Hold, ele segura o último frame, mas continua mandando no personagem e bloqueia o Animator. A saída é terminar a cutscene com o personagem numa pose que o gameplay consegue assumir e devolver o controle por Signal.
Como chamar uma função de script no meio da Timeline?
Use Signals. Crie um Signal asset, coloque um Signal Emitter na Timeline no momento desejado e adicione um Signal Receiver no objeto ligado à faixa. No Receiver, escolha a função que roda como reação, do mesmo jeito que um evento de botão de UI.
Como pular uma cutscene da Timeline por script?
Leve o tempo do PlayableDirector para o fim (director.time = director.duration), chame director.Evaluate() para aplicar o estado final e depois director.Stop(). O Stop encerra a Timeline como no fim normal, então o que precisa continuar como no último frame (porta aberta, personagem no lugar novo) deve ser garantido pelo seu código de fim de cutscene, que o mesmo método de pular chama, já que os Signals do fim não disparam quando você salta o tempo.


