Blueprints: Eventos e fluxo de execução para lógica de gameplay

Capítulo 4

Tempo estimado de leitura: 9 minutos

+ Exercício

Event Graph: onde a lógica “acontece”

No Blueprint, a maior parte da lógica de gameplay fica no Event Graph. Ele é um grafo orientado por eventos: algo acontece (um evento dispara) e a execução percorre uma cadeia de nós. Diferente de um script que roda “de cima para baixo”, aqui a ordem depende de quem dispara e de como os fios de execução (Exec) estão conectados.

Nós de execução (Exec) e nós de dados

Existem dois tipos de conexões principais:

  • Exec (fio branco): controla a ordem de execução. Um nó só “roda” quando recebe Exec.
  • Dados: valores (bool, float, vector, referências etc.). Eles fluem para dentro/fora dos nós, mas não determinam por si só quando algo executa.

Uma regra prática: se um nó tem pino Exec, ele é “imperativo” (faz algo em um momento). Se não tem Exec, geralmente é um nó “puro” (pure), que apenas calcula/retorna um valor quando necessário.

Ordem de execução: o que realmente roda primeiro

Em Blueprints, a ordem é definida pelo caminho do Exec. Se você ligar um evento a uma sequência de nós, eles serão executados na ordem do encadeamento. Se você dividir a execução em múltiplos caminhos, a ordem passa a depender do nó que faz a divisão (por exemplo, Sequence) e do evento que disparou.

BeginPlay: inicialização segura

Event BeginPlay dispara quando o jogo começa (ou quando o ator é spawnado durante o jogo). Use para:

Continue em nosso aplicativo e ...
  • Ouça o áudio com a tela desligada
  • Ganhe Certificado após a conclusão
  • + de 5000 cursos para você explorar!
ou continue lendo abaixo...
Download App

Baixar o aplicativo

  • Inicializar variáveis e estados (ex.: luz começa apagada).
  • Configurar referências (ex.: pegar um componente específico).
  • Disparar timers/rotinas controladas.

Evite colocar lógica que depende de input do jogador ou de colisões aqui, a menos que seja para preparar o estado inicial.

Tick: atualização contínua (e quando evitar)

Event Tick roda a cada frame. Ele é útil para coisas que realmente precisam ser atualizadas continuamente (ex.: interpolação manual, checagens de mira, UI dinâmica complexa). Porém, é fácil criar custo desnecessário.

Quando evitar Tick:

  • Quando você pode reagir a eventos (overlap, input, timers).
  • Quando a lógica só precisa rodar “de vez em quando”.
  • Quando você está apenas esperando algo acontecer.

Alternativas comuns: OnComponentBeginOverlap/OnComponentEndOverlap, Set Timer by Event, Timeline e eventos de input.

Eventos de colisão/overlap e eventos de input

Overlap: entrar/sair de uma área

Eventos de overlap são ideais para “gatilhos” de gameplay: quando algo entra ou sai de um volume/área. Em geral, você usa um componente de colisão (ex.: Box Collision) e conecta:

  • OnComponentBeginOverlap: disparado ao entrar.
  • OnComponentEndOverlap: disparado ao sair.

Esses eventos fornecem informações como Other Actor (quem entrou/saiu) e Other Comp. É comum filtrar para reagir apenas ao jogador.

Input: ações e eixos

Eventos de input disparam quando o jogador pressiona/solta teclas ou move controles. Em Blueprints, você costuma trabalhar com:

  • Action (pressionou/soltou): bom para interagir, pular, abrir porta.
  • Axis (valor contínuo): bom para movimento, câmera, aceleração.

Uma prática importante: mantenha a lógica de input no Pawn/Character/PlayerController quando possível, e faça os atores do mundo reagirem a chamadas/eventos (para não espalhar input em muitos lugares). Para este capítulo, vamos focar no uso de overlap, que é um padrão muito comum e eficiente.

Nós de controle de fluxo essenciais

Branch (if)

Branch recebe um booleano e escolhe entre dois caminhos: True ou False. Use para validações (ex.: “já está acesa?”).

Exec → Branch(Condition = bIsLightOn) → True: (não faz nada) / False: TurnOn

Sequence (executar em passos)

Sequence divide um Exec em múltiplas saídas (Then 0, Then 1...). Ele garante a ordem: executa Then 0, depois Then 1, etc. Útil para organizar ações que precisam ocorrer em sequência sem criar um “fio longo”.

DoOnce (executar uma vez)

DoOnce deixa passar a execução apenas na primeira vez. Depois bloqueia até receber Reset. É ótimo para evitar repetição de efeitos (som, partículas, logs) quando um evento pode disparar várias vezes.

Exemplo: tocar um som apenas na primeira entrada na área, e resetar quando sair.

Gate (abrir/fechar passagem)

Gate funciona como uma “porta” para Exec:

  • Enter: tenta passar.
  • Open: abre a porta.
  • Close: fecha a porta.
  • Toggle: alterna.
  • Start Closed: começa fechada.

Use quando você quer permitir execução apenas em certas condições temporais (ex.: só permitir acender enquanto o jogador estiver dentro).

Delay (espera)

Delay pausa a cadeia de Exec por um tempo e continua depois. Use com cuidado: delays em excesso podem dificultar depuração. Para rotinas repetidas, prefira timers; para animações, prefira timelines.

Timeline (animação/curvas no tempo)

Timeline permite variar valores ao longo do tempo usando curvas (float, vector, color). É excelente para:

  • Fade in/out de luz (intensidade).
  • Abrir porta suavemente (rotação).
  • Interpolar parâmetros de material.

Ela tem pinos como Play, Reverse, Update (a cada passo) e Finished.

Exemplo controlado: mecanismo de luz por área (com proteção contra repetição)

Objetivo: criar um ator que contém uma área de trigger. Quando o jogador entra, a luz acende com transição suave. Quando sai, a luz apaga com transição suave. Além disso, vamos proteger para não repetir efeitos indevidamente (por exemplo, não disparar “acender” se já estiver acesa, e não tocar efeitos repetidamente em overlaps múltiplos).

Estrutura do Blueprint

Crie um Blueprint Actor chamado BP_LightTrigger e adicione componentes:

  • Box Collision (ex.: TriggerBox): define a área.
  • Point Light (ex.: PointLight): a luz que será controlada.
  • (Opcional) Static Mesh: para visualizar um poste/luminária.

Variáveis recomendadas:

  • bIsPlayerInside (Boolean, default: false)
  • bIsLightOn (Boolean, default: false)
  • TargetIntensity (Float, default: 5000 por exemplo)
  • FadeDuration (Float, default: 0.5)

Passo 1 — Configurar estado inicial no BeginPlay

No Event BeginPlay:

  • Defina a intensidade inicial da luz para 0 (apagada).
  • Garanta que bIsLightOn esteja false.
BeginPlay → PointLight.SetIntensity(0) → Set bIsLightOn = false

Isso evita que a luz comece em um estado inesperado.

Passo 2 — Criar a Timeline de fade

Adicione uma Timeline chamada TL_LightFade com:

  • Uma trilha Float chamada Alpha indo de 0 a 1.
  • Duração = FadeDuration (você pode ajustar a duração no próprio Timeline ou multiplicar o valor).

No Update da Timeline:

  • Use Lerp (Float) para interpolar intensidade.
  • Quando acendendo: Lerp de 0 → TargetIntensity.
  • Quando apagando: você pode usar Reverse na timeline para voltar de 1 → 0 e manter o mesmo Lerp.
TL(Update) → SetIntensity( Lerp(0, TargetIntensity, Alpha) )

Assim, você não precisa de Tick: a Timeline já atualiza apenas durante a transição.

Passo 3 — Overlap Begin: entrar na área e acender

No evento TriggerBox.OnComponentBeginOverlap:

  1. Filtre para reagir apenas ao jogador (ex.: checar se Other Actor é do tipo Character do jogador). Uma forma comum é Cast To para seu Character; outra é comparar com Get Player Character.
  2. Defina bIsPlayerInside = true.
  3. Use Branch para não acender se já estiver acesa.
  4. Se estiver apagada, acione a Timeline com Play e marque bIsLightOn = true.
BeginOverlap → (validar jogador) → Set bIsPlayerInside=true → Branch(bIsLightOn?) → False: TL_LightFade.Play → Set bIsLightOn=true

Proteção contra repetição: o Branch impede que múltiplos overlaps (por exemplo, por componentes diferentes do personagem) reexecutem o “acender”.

Passo 4 — Overlap End: sair da área e apagar

No evento TriggerBox.OnComponentEndOverlap:

  1. Valide que quem saiu é o jogador.
  2. Defina bIsPlayerInside = false.
  3. Use Branch para não apagar se já estiver apagada.
  4. Se estiver acesa, use Reverse na Timeline e marque bIsLightOn = false.
EndOverlap → (validar jogador) → Set bIsPlayerInside=false → Branch(bIsLightOn?) → True: TL_LightFade.Reverse → Set bIsLightOn=false

Isso garante que a luz só apaga quando realmente estava acesa.

Refinando a proteção: DoOnce e Gate em cenários comuns

Problema comum: múltiplos BeginOverlap seguidos

Dependendo da configuração de colisão, um personagem pode gerar overlaps múltiplos (por exemplo, cápsula + malha). O Branch(bIsLightOn) já evita repetir o estado, mas você pode querer evitar repetir efeitos adicionais (som, partículas, mensagens).

Aplicando DoOnce para efeitos de entrada/saída

Suponha que você quer tocar um som ao acender e outro ao apagar, mas apenas uma vez por entrada/saída.

  • Coloque um DoOnce antes do “som de acender”.
  • Resete esse DoOnce quando o jogador sair.
BeginOverlap(validado) → DoOnce → PlaySound(Enter) → (resto do acender)
EndOverlap(validado) → DoOnce.Reset → PlaySound(Exit) → (resto do apagar)

Assim, mesmo que o BeginOverlap dispare duas vezes, o som não repete.

Aplicando Gate para bloquear ações fora da área

Agora imagine uma variação: a luz só pode ser acionada por input (tecla) enquanto o jogador estiver dentro da área. Você pode usar um Gate:

  • No BeginOverlap: Open o Gate.
  • No EndOverlap: Close o Gate.
  • No evento de input (ex.: InputAction Interact): conecte no Enter do Gate e, depois, faça a lógica de alternar a luz.
BeginOverlap(validado) → Gate.Open
EndOverlap(validado) → Gate.Close
InputAction Interact(Pressed) → Gate.Enter → (toggle da luz)

Isso evita checagens constantes e mantém o fluxo explícito.

Usando Sequence e Delay de forma controlada (sem virar “bagunça”)

Sequence para organizar ações de entrada

No BeginOverlap, você pode querer: (1) acender a luz, (2) tocar som, (3) disparar uma partícula. Em vez de encadear tudo em um fio longo, use Sequence:

BeginOverlap(validado) → Sequence → Then0: (lógica da luz) → Then1: (som) → Then2: (partícula)

Isso mantém o grafo legível e a ordem explícita.

Delay para um “auto-off” (opcional)

Se você quiser que a luz apague após alguns segundos mesmo com o jogador dentro, você pode usar Delay com uma proteção para não conflitar com a saída:

  • Ao entrar: acende, depois Delay(3s), e então apaga somente se bIsPlayerInside for false (ou true, dependendo da regra).
BeginOverlap(validado) → (acende) → Delay(3.0) → Branch(bIsPlayerInside?)

Esse padrão mostra por que Branch e variáveis de estado são importantes: sem isso, o Delay poderia apagar a luz mesmo com o jogador ainda dentro.

Tabela rápida: qual nó usar em cada situação

NecessidadeNó recomendadoObservação
Decidir entre dois caminhosBranchBase para validações e estados
Executar passos em ordemSequenceOrganiza sem “fio infinito”
Evitar repetição até resetDoOnceÓtimo para efeitos (som/partícula)
Permitir execução só em certas condiçõesGateExcelente com overlap + input
Esperar um tempo e continuarDelayUse com parcimônia; cuidado com estados
Interpolar valores no tempoTimelineSubstitui Tick em muitos casos

Agora responda o exercício sobre o conteúdo:

Em um Blueprint, qual abordagem é mais adequada para fazer a intensidade de uma luz mudar suavemente ao longo do tempo, sem depender de atualização a cada frame?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

A Timeline atualiza valores durante a transição (pino Update) e permite interpolar com Lerp, evitando manter lógica rodando no Tick quando ne3o e9 necesse1rio.

Próximo capitúlo

Variáveis, tipos de dados e estruturas de controle em Blueprints

Arrow Right Icon
Capa do Ebook gratuito Unreal Engine para Iniciantes: Fundamentos de Blueprints e Lógica de Gameplay
24%

Unreal Engine para Iniciantes: Fundamentos de Blueprints e Lógica de Gameplay

Novo curso

17 páginas

Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.