Sistema de interação: pegar, usar e inspecionar objetos com Blueprints

Capítulo 8

Tempo estimado de leitura: 10 minutos

+ Exercício

Objetivo do sistema de interação

Um sistema de interação em primeira/terceira pessoa normalmente resolve três problemas: detectar o que o jogador está mirando, comunicar ao jogador que algo é interagível (feedback visual) e executar uma ação ao pressionar uma tecla (pegar, usar, inspecionar). Neste capítulo, você vai montar um fluxo completo com: Line Trace (raycast), filtragem por canal/objetos, highlight simples, tecla de Interagir, inventário básico via Array, uso/consumo de item e depuração com Draw Debug.

Arquitetura sugerida (simples e escalável)

  • BP_PlayerCharacter: faz o Line Trace, decide o alvo atual, mostra feedback e chama a interação ao apertar a tecla.
  • BP_InteractableBase: ator base para objetos interagíveis (pegar/usar/inspecionar). Contém dados do item e implementa a resposta ao interagir.
  • Inventário simples: um Array no Player com itens (por exemplo, uma struct com ID, nome, tipo, efeito).
  • Highlight: via Custom Depth/Stencil (recomendado) ou troca de material (mais simples, porém mais intrusivo).

Preparação: canal de trace e tags de interagível

Criar um Trace Channel para interação

Para evitar que o raycast acerte coisas irrelevantes (parede, chão, etc.), crie um canal dedicado.

  • Project Settings > Collision > Trace Channels > New Trace Channel: InteractTrace (Default Response: Ignore).
  • Nos objetos interagíveis, em Collision, defina a resposta para InteractTrace como Block.

Alternativa: Object Types (filtragem por tipo)

Se preferir, você pode usar LineTraceForObjects e filtrar por tipos (WorldDynamic, PhysicsBody). A abordagem por canal costuma ser mais previsível para interação.

Dados do item: struct e enum (inventário simples)

Para o inventário, crie uma estrutura de dados mínima para representar itens.

Enum de tipo de item

  • EItemType: Consumable, KeyItem, Inspectable.

Struct do item

Crie ST_ItemData com campos:

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

  • ItemID (Name)
  • DisplayName (Text)
  • ItemType (EItemType)
  • UseValue (Float) — por exemplo, cura/energia
  • PickupSFX (SoundBase, opcional)
  • PickupVFX (NiagaraSystem/ParticleSystem, opcional)

No Player, crie Inventory como Array<ST_ItemData>.

BP_InteractableBase: ator interagível com ações

Componentes recomendados

  • StaticMesh (ou SkeletalMesh): o visual do item.
  • Sphere Collision (opcional): útil para limitar interação por proximidade, mas o Line Trace já resolve. Se usar, combine as duas coisas (trace + distância).

Variáveis

  • ItemData (ST_ItemData) — Instance Editable para configurar por item no level.
  • bCanBePickedUp (bool)
  • bCanBeInspected (bool)
  • bCanBeUsedDirectly (bool) — se o item pode ser usado no mundo (ex.: botão/terminal) ou se só faz sentido no inventário.

Eventos/Functions no Interactable

Crie funções (ou eventos) para padronizar o comportamento:

  • GetInteractText(out Text): retorna “Pegar”, “Usar”, “Inspecionar” conforme o item.
  • OnFocused(): liga highlight.
  • OnUnfocused(): desliga highlight.
  • Interact(Interactor): executa a ação principal quando o jogador pressiona Interagir.

Highlight simples com Custom Depth

Uma forma comum é habilitar Custom Depth no mesh e usar um Post Process para contorno. Mesmo sem Post Process, você pode usar Custom Depth como base para um highlight simples (dependendo do seu setup). O essencial aqui é alternar a flag.

  • No StaticMesh: marque Render CustomDepth Pass como false por padrão.
  • Em OnFocused(): Set Render CustomDepth = true.
  • Em OnUnfocused(): Set Render CustomDepth = false.

Se você não estiver usando Post Process, uma alternativa é trocar material para um “material emissivo” enquanto focado. Só evite esquecer de restaurar o material original (guarde referência).

Detecção: Line Trace no Player (raycast)

Variáveis no Player

  • InteractDistance (float) — ex.: 250–400.
  • CurrentFocusedActor (Actor ref) — alvo atual.
  • LastFocusedActor (Actor ref) — para desligar highlight ao trocar alvo.
  • bDrawDebugInteract (bool) — para depuração.

Passo a passo: montar o trace

No Event Tick (ou em um Timer a cada 0.05s para otimizar), faça:

  1. Obter posição e direção da câmera: Get Player Camera Manager ou componente de câmera do personagem.
  2. Start = Camera Location.
  3. End = Start + (Camera Forward Vector * InteractDistance).
  4. Executar LineTraceByChannel usando o canal InteractTrace.
  5. Ativar Draw Debug Type como For Duration quando bDrawDebugInteract for true.
Start = CameraLocation End = Start + ForwardVector * InteractDistance LineTraceByChannel(Channel=InteractTrace, DrawDebug=Conditional)

Filtragem e validação do alvo

Após o trace:

  • Se Hit for false: não há alvo. Limpe foco e UI de interação.
  • Se Hit Actor for válido: confirme se é interagível. Você pode usar uma das estratégias:
  • Por classe base: Cast para BP_InteractableBase.
  • Por interface (mais flexível): criar uma Blueprint Interface BPI_Interactable com OnFocused, OnUnfocused, Interact, GetInteractText. (Se você já usa interfaces no projeto, essa é a melhor opção.)
  • Por tag: Actor Has Tag = “Interactable”. Útil como filtro extra, mas não substitui a necessidade de funções de interação.

Mesmo usando classe base, trate o caso de “acertou algo que bloqueia o canal mas não é interagível” (erro comum quando configurações de colisão estão inconsistentes).

Gerenciar foco (ligar/desligar highlight)

Fluxo recomendado:

  • Se o novo alvo é diferente do anterior: chame OnUnfocused no anterior (se válido) e OnFocused no novo.
  • Atualize LastFocusedActor e CurrentFocusedActor.
If HitActor != CurrentFocusedActor: If CurrentFocusedActor valid: CurrentFocusedActor.OnUnfocused() CurrentFocusedActor = HitActor CurrentFocusedActor.OnFocused()

Se não houver Hit, mas CurrentFocusedActor era válido, chame OnUnfocused e zere a referência.

Tecla de Interagir: executar ação com tratamento de erros

Input Action

Crie uma Action Mapping (ou Enhanced Input) chamada Interact e associe a tecla E (ou a que preferir).

Lógica ao pressionar Interact

No evento de input:

  1. Se CurrentFocusedActor não é válido: exiba um feedback leve (opcional) e saia.
  2. Se é válido, chame Interact no alvo, passando referência do Player (Interactor).
  3. Se a chamada falhar (ex.: alvo destruído no mesmo frame), trate com IsValid antes de chamar.
OnInteractPressed: If !IsValid(CurrentFocusedActor): PrintString("Sem alvo") return CurrentFocusedActor.Interact(self)

Implementar “Pegar item”: ocultar/desativar, VFX/SFX e adicionar ao inventário

Regras do pickup

  • O item deve sumir do mundo (ocultar mesh e desabilitar colisão) ou ser destruído.
  • Deve tocar som/partícula (se configurado).
  • Deve adicionar ItemData ao Inventory do Player.

Passo a passo no BP_InteractableBase (Interact)

Dentro de Interact(Interactor):

  1. Validar Interactor (IsValid). Se inválido, PrintString e retorne.
  2. Checar bCanBePickedUp. Se false, pode cair no modo “Inspecionar” ou “Usar” dependendo do item.
  3. Adicionar ao inventário: no Interactor (Player), chame uma função AddItemToInventory(ItemData).
  4. Tocar SFX: Play Sound at Location com PickupSFX se válido.
  5. Tocar VFX: Spawn System at Location com PickupVFX se válido.
  6. Remover do mundo: opção A) Set Actor Enable Collision(false) + Set Actor Hidden In Game(true); opção B) Destroy Actor.

Para evitar bugs de “pegar duas vezes”, desative colisão imediatamente antes de tocar efeitos ou adicionar ao inventário.

Função no Player: AddItemToInventory

No Player, crie:

  • AddItemToInventory(ItemData):
  1. Validar se ItemData.ItemID não está vazio (opcional).
  2. Inventory.Add(ItemData).
  3. Opcional: PrintString com o nome do item para confirmar.

Implementar “Usar item”: consumir do inventário e aplicar efeito

Modelo simples de uso (consumível)

Vamos supor um item consumível que cura o jogador. Você pode “usar” via UI/inventário, mas aqui vamos focar na lógica: remover do Array e aplicar um efeito.

Variáveis de status no Player

  • Health (float)
  • MaxHealth (float)

Função: UseItemByIndex (inventário)

No Player:

  1. Entrada: Index (int).
  2. Validar: Inventory.IsValidIndex(Index). Se não, PrintString “Índice inválido” e retorne.
  3. Item = Inventory[Index].
  4. Switch em Item.ItemType:
  • Consumable: aplicar efeito (ex.: Health = Clamp(Health + Item.UseValue, 0, MaxHealth)) e então Inventory.RemoveAt(Index).
  • KeyItem: normalmente não consome; pode apenas disparar lógica contextual (depende do jogo).
  • Inspectable: abrir modo de inspeção (ver seção abaixo) sem consumir.
UseItemByIndex(Index): if !Inventory.IsValidIndex(Index) return Item = Inventory[Index] switch(ItemType) Consumable: Health = Clamp(Health + UseValue, 0, MaxHealth) Inventory.RemoveAt(Index)

Usar item diretamente no mundo (opcional)

Se você quer que alguns atores sejam “usáveis” (ex.: alavanca), implemente em BP_InteractableBase um modo bCanBeUsedDirectly e, no Interact, execute uma ação sem adicionar ao inventário (por exemplo, tocar animação, mudar estado, abrir porta). Mantenha o mesmo tratamento de erros: alvo inválido, estado não permite uso, etc.

Implementar “Inspecionar”: modo simples e seguro

Inspecionar pode ser tão simples quanto mostrar um texto/tooltip, ou tão completo quanto “pegar o objeto e rotacionar na tela”. Aqui vai um modelo simples e prático sem UI complexa:

Inspeção por tooltip (rápida)

  • No GetInteractText, retorne “Inspecionar” para itens do tipo Inspectable.
  • No Interact, se bCanBeInspected for true, faça PrintString com ItemData.DisplayName e talvez uma descrição (se você adicionar no struct).

Inspeção com “freeze” e rotação (intermediária)

Se quiser um passo além:

  • Ao inspecionar: desabilite input de movimento, mantenha o mouse para rotacionar um mesh em frente à câmera (pode ser um componente separado ou um ator “preview”).
  • Saída da inspeção: reabilite input e destrua/oculte o preview.

Esse modo exige mais controle de câmera/UI, então mantenha como extensão opcional do sistema.

Feedback visual e texto de interação

Mostrar “Pressione E para ...”

Mesmo sem construir UI completa, você pode usar um Widget simples com um TextBlock. O Player atualiza o texto com base no alvo focado:

  • Se CurrentFocusedActor válido: chamar GetInteractText e exibir.
  • Se inválido: esconder o widget.

Se você ainda não tem widget, use PrintString temporariamente para validar o fluxo.

Tratamento de erros comuns (e como evitar)

1) “Sem alvo” ao apertar Interagir

  • Confirme se o trace está partindo da câmera (não do capsule).
  • Aumente InteractDistance.
  • Ative bDrawDebugInteract para ver a linha.

2) Trace acerta o objeto, mas não interage

  • Verifique Collision do objeto: resposta ao canal InteractTrace deve ser Block.
  • Verifique se o ator realmente é do tipo interagível (classe base/interface).
  • Se estiver usando highlight por mesh, confirme que o mesh existe e é o componente correto.

3) Highlight “fica preso” quando olha para outro lugar

  • Garanta que, quando não houver Hit, você chama OnUnfocused no alvo anterior.
  • Garanta que, ao trocar de alvo, você desliga o highlight do anterior antes de ligar no novo.

4) Pegar duas vezes o mesmo item

  • Desabilite colisão imediatamente no início do pickup.
  • Use um bool bIsCollected no interagível para bloquear reentrada.

Depuração com Draw Debug e logs

Draw Debug no Line Trace

Em LineTraceByChannel, use Draw Debug Type:

  • None em produção.
  • For One Frame para checagens rápidas.
  • For Duration para observar enquanto testa.

Combine com PrintString exibindo: nome do Hit Actor, distância e o texto de interação retornado.

Tabela rápida: o que checar quando algo falha

SintomaChecagemCorreção típica
Não aparece debug lineTick/Timer está rodando?Conectar execução e habilitar flag
Debug line passa pelo itemCanal/colisãoBlock em InteractTrace
Hit ocorre, mas não há focoFiltro de interagívelClasse base/interface/tag
Interagir não faz nadaInput mappingVerificar Action/Enhanced Input e possess
Inventário não recebe itemFunção AddItemValidar Interactor e ItemData

Checklist final do sistema (para testar rapidamente)

  • Line Trace atinge apenas interagíveis (canal InteractTrace).
  • Ao mirar: highlight liga; ao sair: highlight desliga.
  • Tecla Interagir sem alvo: não quebra (tratamento com IsValid).
  • Pegar item: toca SFX/VFX (se houver), some do mundo e entra no Inventory.
  • Usar item consumível: aplica efeito e remove do Array.
  • Draw Debug habilitável por bool para depuração.

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

Qual fluxo evita que o highlight fique “preso” ao mudar o alvo de interação durante o Line Trace?

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

Você errou! Tente novamente.

O highlight deve seguir o foco. Ao trocar de alvo, desligue primeiro no anterior (OnUnfocused) e só então ligue no novo (OnFocused). Se não houver Hit, desligue o highlight e zere o alvo atual para evitar estado preso.

Próximo capitúlo

Input e controle do personagem: ações, eixos e resposta de gameplay

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

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.