Referências, casting e comunicação entre Blueprints (sem acoplamento excessivo)

Capítulo 7

Tempo estimado de leitura: 12 minutos

+ Exercício

Por que “referências” importam em Blueprints

Em Blueprints, quase toda interação de gameplay depende de você ter uma referência para algum objeto no mundo (um Actor, um Component, o Player, um Widget, etc.). Uma referência é “um ponteiro” para uma instância específica em tempo de execução: com ela você consegue ler variáveis, chamar funções, disparar eventos e acessar componentes.

O desafio é obter e manter essas referências sem criar acoplamento excessivo (quando um Blueprint depende diretamente do tipo concreto do outro, dificultando reuso e manutenção). Este capítulo foca em: formas comuns de obter referências, o que é Cast To e quando evitar, e como usar Blueprint Interfaces e Event Dispatchers para comunicação desacoplada.

Formas comuns de obter referências (com exemplos)

1) Get Player Character / Get Player Controller

Use quando você precisa acessar o personagem/controlador do jogador local (single player ou player index específico). É direto e barato, mas ainda cria dependência se você fizer cast para uma classe específica.

  • Quando usar: interações que sempre envolvem o jogador local (ex.: abrir inventário, atualizar HUD, checar posição do player).
  • Cuidado: em projetos com múltiplos personagens jogáveis, evite assumir uma classe concreta sem necessidade.

Exemplo prático: em um Actor do cenário, obter o player e ler a localização.

Get Player Character (Player Index 0) -> Get Actor Location

2) Get Actor of Class / Get All Actors of Class

Esses nós procuram Actors no mundo por classe.

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

  • Get Actor of Class: retorna o primeiro encontrado. Útil quando você tem certeza que existe apenas um (ex.: um “GameManager” único).
  • Get All Actors of Class: retorna uma lista. Útil para iterar, mas pode ser custoso se usado com frequência.

Boas práticas:

  • Evite chamar a cada Tick. Prefira chamar uma vez (ex.: no BeginPlay) e guardar em variável.
  • Para “singletons” de gameplay, considere guardar referência em um lugar central (GameMode/GameState/Subsystem) e injetar por variável exposta (ver abaixo).

3) Overlap: Other Actor (eventos de colisão)

Em eventos como OnComponentBeginOverlap ou ActorBeginOverlap, o parâmetro Other Actor já é uma referência para quem entrou na área de colisão.

  • Quando usar: interações por proximidade (gatilhos, pickups, áreas de dano, portas com trigger).
  • Cuidado: Other Actor é do tipo Actor genérico; você pode filtrar por tags, interfaces, componentes ou (se necessário) cast.

Exemplo de filtragem sem cast: checar se o outro actor implementa uma interface (ver seção de Interfaces).

4) Variável exposta (Instance Editable / Expose on Spawn)

Uma forma muito limpa de obter referência é recebê-la em vez de procurar. Você cria uma variável do tipo referência (ex.: BP_Porta, Actor, ou melhor: uma Interface) e marca como:

  • Instance Editable: para setar no Details Panel ao colocar o Actor no nível.
  • Expose on Spawn: para passar a referência no momento do SpawnActor.

Vantagem: reduz buscas no mundo e diminui acoplamento quando você usa tipos mais genéricos (Actor/Interface) em vez de classes concretas.

AbordagemPrósContras
Procurar (Get Actor of Class)Rápido de prototiparPode ser custoso e frágil (depende do mundo)
Receber por variável expostaExplícito, performático, fácil de manterRequer configurar no editor/spawn

O que é Cast To (e por que ele acopla)

Cast To tenta tratar uma referência genérica (ex.: Actor) como uma classe específica (ex.: BP_PlayerCharacter). Se o objeto em runtime for daquela classe (ou derivada), o cast “passa” e você ganha acesso às variáveis/funções específicas.

Quando faz sentido usar Cast To

  • Quando você realmente precisa de algo específico daquela classe (uma função/variável que não existe em um tipo mais genérico).
  • Quando a relação é naturalmente “forte” e estável (ex.: seu HUD sabe que o PlayerController é de uma classe específica do seu jogo).
  • Quando você controla o fluxo e tem certeza do tipo (ex.: acabou de dar Spawn em uma classe específica e guardou como Actor genérico por algum motivo).

Quando evitar Cast To

  • Quando você está fazendo cast em muitos lugares só para chamar uma ação simples (ex.: “Interagir”, “Receber Dano”, “Abrir”).
  • Quando vários objetos diferentes deveriam responder à mesma ação (porta, alavanca, NPC, item) e você acabaria criando uma cadeia de casts.
  • Quando o cast vira dependência circular: A conhece B e B conhece A por classes concretas.

Alternativas comuns ao cast: Blueprint Interfaces (para chamar ações comuns) e Event Dispatchers (para notificar eventos sem conhecer o ouvinte).

Blueprint Interfaces: comunicação por contrato (desacoplada)

Uma Blueprint Interface (BPI) define um conjunto de funções (assinaturas) que qualquer Blueprint pode implementar. Quem chama não precisa saber a classe concreta; só precisa de uma referência para um objeto que implemente a interface.

Vantagens

  • Evita cadeias de Cast To.
  • Permite múltiplos tipos de objetos responderem à mesma ação.
  • Facilita reuso e testes (você troca implementações sem mudar quem chama).

Como chamar uma Interface

Em geral você usa:

  • Does Implement Interface para checar.
  • Chamada da função da interface (mensagem) no alvo (Target).

Se o alvo não implementar, a chamada não executa (ou você pode proteger com a checagem).

Event Dispatchers: “broadcast” de eventos para ouvintes

Um Event Dispatcher é um mecanismo de evento: um Blueprint “emite” (Broadcast/Call) e outros Blueprints “assinam” (Bind) para reagir. O emissor não precisa conhecer quem está ouvindo.

Quando usar Dispatchers

  • Quando um objeto precisa avisar “algo aconteceu” para vários interessados (ex.: botão pressionado, porta abriu, item coletado).
  • Quando você quer que o Player (ou HUD) reaja a eventos de objetos do mundo sem cast direto.

Pontos de atenção

  • Você precisa ter uma referência para fazer o Bind (normalmente no BeginPlay, ao entrar em overlap, ou ao registrar um sistema).
  • Se o objeto emissor for destruído, bindings deixam de ser relevantes; ainda assim, evite manter referências inválidas e prefira checar validade quando necessário.

Exercício prático: Interface BPI_Interagivel + resposta no jogador sem cast direto

Objetivo: criar uma interface BPI_Interagivel com a ação Interagir. Um objeto do cenário (ex.: uma alavanca) implementa essa interface. Ao interagir, ele dispara uma resposta no jogador sem cast direto, usando um Event Dispatcher no próprio jogador (ou no Controller) para notificar “Interação ocorreu”.

Parte A — Criar a Interface BPI_Interagivel

  1. Content Browser > Add > Blueprints > Blueprint Interface.
  2. Nomeie como BPI_Interagivel.
  3. Abra a interface e crie uma função chamada Interagir.
  4. Adicione um parâmetro de entrada opcional para contexto, por exemplo: Interagente do tipo Actor (Object Reference). Isso permite que o objeto saiba “quem interagiu”.

Assinatura sugerida:

Interagir(Interagente: Actor)

Parte B — Criar um objeto interagível no cenário (ex.: BP_Alavanca)

  1. Crie um Blueprint Actor chamado BP_Alavanca.
  2. Adicione um Static Mesh (visual) e, se quiser interação por proximidade, um Box Collision.
  3. Em Class Settings > Interfaces > Add > selecione BPI_Interagivel.
  4. No Event Graph, implemente o evento/função da interface: procure por Event Interagir (ou a entrada equivalente da interface).

Lógica sugerida dentro de BP_Alavanca (sem cast para o player):

  • Ao receber Interagir(Interagente), valide se Interagente é válido.
  • Em vez de cast para BP_Player, você vai chamar um dispatcher no interagente via uma referência já conhecida (ver Parte C) ou via uma interface adicional (opcional). Para manter o exercício alinhado, vamos usar um dispatcher no jogador e fazer o Bind no jogador quando ele detectar o interagível.

Como o dispatcher será do jogador, a alavanca precisa de um jeito de “avisar” o jogador. Uma abordagem simples e desacoplada é: a alavanca expõe um dispatcher próprio e o jogador se inscreve; ou o jogador expõe um dispatcher e a alavanca chama. A opção mais comum é o objeto do mundo emitir e o jogador ouvir. Vamos seguir essa (mais desacoplada).

Parte C — Adicionar um Event Dispatcher no BP_Alavanca (emissor)

  1. No BP_Alavanca, crie um Event Dispatcher chamado OnInteragido.
  2. Adicione um parâmetro no dispatcher: Interagente (Actor).
  3. Na implementação de Interagir, chame OnInteragido (Call/Broadcast) passando o Interagente.
Event Interagir(Interagente) -> Call OnInteragido(Interagente)

Opcionalmente, você pode também tocar uma animação, mudar material, ou alternar um booleano interno (ex.: bLigada) antes de emitir o evento.

Parte D — No jogador: detectar interagíveis e chamar a Interface

Você precisa de um fluxo de interação. Um padrão simples:

  • O jogador mantém uma variável AlvoInteracao (tipo Actor).
  • Quando entra em overlap com um interagível, define AlvoInteracao.
  • Quando aperta a tecla de interação (ex.: E), chama a interface Interagir no alvo.

Passo a passo (Player Character):

  1. No Blueprint do Player Character, adicione um Sphere/Box Collision (ex.: InteractionSphere) para detectar objetos próximos.
  2. No InteractionSphere, use OnComponentBeginOverlap e OnComponentEndOverlap.
  3. Crie a variável AlvoInteracao (tipo Actor).
  4. No BeginOverlap: se Other Actor Does Implement Interface (BPI_Interagivel), então set AlvoInteracao = Other Actor.
  5. No EndOverlap: se Other Actor == AlvoInteracao, então limpe AlvoInteracao (set None).
  6. Crie um Input Action (ex.: Interact) e, ao pressionar, se AlvoInteracao for válido e implementar a interface, chame Interagir passando Self como Interagente.
Input Interact Pressed -> IsValid(AlvoInteracao) -> Does Implement Interface (BPI_Interagivel) -> Interagir (Message) Target=AlvoInteracao Interagente=Self

Note que aqui não existe cast para BP_Alavanca, BP_Porta, etc. O jogador só exige que o alvo seja “interagível”.

Parte E — Resposta no jogador sem cast direto: Bind no dispatcher do interagível

Agora vamos fazer o jogador reagir ao evento emitido pelo objeto (alavanca) sem cast para uma classe específica do objeto.

Como o dispatcher OnInteragido está no BP_Alavanca, para fazer Bind você precisaria de uma referência tipada (ou cast). Para manter zero cast, a solução é mover o dispatcher para uma interface também (não dá: interfaces não carregam dispatchers), ou criar um componente comum, ou usar uma segunda interface para “registrar” callbacks. Para este exercício, vamos usar uma abordagem prática e comum: criar um Blueprint Actor Component chamado BPAC_Interagivel que contém o dispatcher, e anexar esse componente a qualquer objeto interagível. Assim, o jogador encontra o componente por tipo (sem cast para a classe do Actor).

Parte F — Criar um Actor Component para padronizar o dispatcher (BPAC_Interagivel)

  1. Crie um Blueprint Actor Component chamado BPAC_Interagivel.
  2. Dentro dele, crie um Event Dispatcher OnInteragido com parâmetro Interagente (Actor).
  3. Adicione uma função pública no componente, por exemplo EmitirInteragido, que chama o dispatcher.
EmitirInteragido(Interagente) -> Call OnInteragido(Interagente)

Parte G — Usar o componente no BP_Alavanca e emitir o evento

  1. No BP_Alavanca, adicione o componente BPAC_Interagivel.
  2. Na implementação de Interagir (da interface), em vez de chamar um dispatcher do próprio actor, chame EmitirInteragido no componente.
Event Interagir(Interagente) -> BPAC_Interagivel->EmitirInteragido(Interagente)

Parte H — No jogador: fazer Bind no dispatcher via componente (sem cast)

Quando o jogador detectar um interagível no overlap, além de setar AlvoInteracao, ele tenta obter o componente BPAC_Interagivel do actor e faz Bind no dispatcher.

  1. No Player Character, crie uma variável InteragivelCompAtual do tipo BPAC_Interagivel (Object Reference).
  2. No BeginOverlap, após confirmar que implementa BPI_Interagivel, use Get Component By Class no Other Actor buscando BPAC_Interagivel.
  3. Se válido, faça Bind Event to OnInteragido e aponte para um Custom Event no jogador (ex.: OnInteragido_Receber).
  4. Guarde esse componente em InteragivelCompAtual.
  5. No EndOverlap, se estiver saindo do mesmo actor, faça Unbind (ou Unbind All com cuidado) e limpe as variáveis.

Custom Event no jogador: OnInteragido_Receber(Interagente). Dentro dele, você pode disparar uma resposta no jogador (ex.: tocar som, mostrar mensagem, incrementar contador).

OnComponentBeginOverlap(OtherActor) -> Does Implement Interface (BPI_Interagivel) -> Set AlvoInteracao = OtherActor -> GetComponentByClass(BPAC_Interagivel) -> Bind Event to OnInteragido
Custom Event OnInteragido_Receber(Interagente) -> (ex.) Print String "Interação recebida no jogador"

Checklist de validação do exercício

  • O jogador chama Interagir via Interface (Message), sem cast para o tipo do objeto.
  • O objeto do cenário implementa BPI_Interagivel e, ao interagir, emite um evento.
  • O jogador reage ao evento via Bind em um dispatcher obtido por componente, sem cast para a classe do objeto.

Padrões úteis para reduzir acoplamento

Prefira “programar para a interface”

  • Variáveis do tipo Interface (quando aplicável) ou Actor + checagem Does Implement Interface.
  • Chamadas por Interface Message para ações genéricas (Interagir, ReceberDano, Ativar).

Use Cast To como ferramenta pontual, não como cola do projeto

  • Se você está fazendo cast repetidamente em vários lugares para chamar a mesma ação, isso é um sinal forte de que uma Interface ou Dispatcher resolveria melhor.
  • Se o cast é inevitável, faça uma vez, armazene a referência tipada e valide (IsValid) antes de usar.

Evite buscas frequentes no mundo

  • Se precisar de um Actor específico, prefira injetar por variável exposta (Instance Editable/Expose on Spawn) ou cachear no BeginPlay.
  • Use Overlap e referências diretas quando a interação for espacial/proximidade.

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

Ao criar um sistema de interação em Blueprints que evite acoplamento excessivo, qual abordagem permite que o jogador chame a ação no objeto e ainda reaja ao evento sem fazer Cast To para a classe concreta do Actor?

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

Você errou! Tente novamente.

Interfaces permitem chamar a ae7e3e3o sem conhecer a classe concreta do alvo. Para reagir a eventos sem cast, o jogador pode obter um componente comum (via Get Component By Class) que expf5e um dispatcher e fazer Bind nele.

Próximo capitúlo

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

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

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.