Buscar

Aula 08 - Física e Colisores


Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 18 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 18 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 18 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Continue navegando


Prévia do material em texto

Desenvolvimento de Jogos Digitais II
Aula 8: Física e Colisores
Apresentação
Qualquer jogo digital está relacionado, de alguma forma, com conceitos matemáticos, como na translação e rotação de
personagens, e a maioria deles precisa utilizar os elementos da física. Quando trabalhamos com alguma Game Engine,
a utilização de forças sobre corpos rígidos trará grande realismo aos movimentos, enquanto o controle da colisão, em
modo de bloqueio ou de gatilho, de�nirá a interatividade entre os atores do jogo.
Objetivo
Analisar os conceitos relacionados à matemática e à física nos jogos;
Usar forças e colisores no ambiente da Unreal Engine;
Construir respostas para as colisões via C++ e Blueprints.
Matemática e Física nos Jogos Digitais
Em termos da álgebra linear, o elemento básico de trabalho são os vetores, segmentos de reta orientados, indicando sentido e
intensidade para alguma grandeza, e que podem representar pontos no plano ou no espaço, quando partem da origem das
coordenadas. Por exemplo, a posição de um ator no espaço é de�nida a partir de um vetor, com as coordenadas X, Y e Z.
Na Unity 3D é possível representar vetores 2D, 3D e 4D com grande facilidade, por meio das classes Vector2, Vector3 e
Vector4, e elas trazem métodos especí�cos para normalização, magnitude, e demais procedimentos matemáticos aplicáveis
aos vetores.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
 
float f;
f = Vector2.Distance(new Vector2(1,3), new Vector2(0,1));
Vector3 v3 = new Vector3(4,5,0);
float a = v3.x;
 Listagem: Fragmento de código com vetores, em C#, para Unity 3D. Fonte: O autor.
Na Unreal Engine, os vetores para 3D são do tipo FVector, e para 2D é utilizado FVector2D, apresentando também diversas
operações disponíveis. As possibilidades trazidas pelo C++, como a sobrecarga de operadores nas classes, são amplamente
utilizadas.
 
float f;
f = Vector2.Distance(new Vector2(1,3), new Vector2(0,1));
Vector3 v3 = new Vector3(4,5,0);
float a = v3.x;
 Listagem: Fragmento de código com vetores, em C++, para Unreal Engine. Fonte: O autor.
A multiplicação por escalar permite modi�car a magnitude de um vetor, ou seja, se você multiplicar todos os vetores de um
conjunto de vértices por um número qualquer, a escala da �gura será modi�cada. Com relação à soma vetorial, ela
representa um deslocamento, ou operação de translação, quando aplicada a todos os vértices da �gura.
 
FVector v1 = FVector(8, 4, 6); // v1 = [8,4,6]
FVector v2 = v1 * 0.5; // v2 = [4,2,3]
FVector v3 = v1 + FVector(2, -2, 2); // v3 = [10,2,8]
FVector v4 = v1 * 0.5 + FVector(2, -2, 2); // v4 = [6,0,5]
 Listagem: Operações algébricas para translação e escala. Fonte: O autor.
O produto escalar e o produto vetorial permitem o reconhecimento do ângulo formado entre dois vetores. Com a utilização
de produto escalar, o resultado da multiplicação é um número simples, enquanto a aplicação do produto vetorial terá como
resultado um novo vetor.
 
FVector v1 = FVector(8, 4, 2), v2 = FVector(5, 3, 0);
float angulo;
// Produto Vetorial -> || A x B || = || A || || B || sen(angulo)
FVector v3 = v1 ^ v2;
angulo = asin(v3.Size() / (v1.Size() * v2.Size()));
// Produto Escalar -> A . B = || A || || B || cos(angulo)
float f4 = v1 | v2;
angulo = acos(f4 / (v1.Size() * v2.Size()));
 Listagem: Cálculo do ângulo a partir do produto escalar e do produto vetorial. Fonte: O autor.
Matrizes também são de grande interesse para a área de jogos e
computação grá�ca em geral, e uma matriz quadrada é aquela que tem a
mesma dimensão para linhas e colunas. Em geral, uma matriz de
transformação M quadrada de�ne qualquer transformação linear a partir da
multiplicação do vetor de coordenadas pela matriz.
Considerando o ambiente 3D, por meio da multiplicação por matrizes 3x3 é possível efetuar as operações de rotação ou
escala de forma simples, mas a translação irá exigir uma dimensão a mais, ou seja, precisamos de uma matriz 4x4. Para sua
utilização será necessário também a transformação do vetor 3D em vetor 4D a partir do acréscimo de um elemento unitário.
Algo interessante acerca das matrizes 4x4 é que elas permitem efetuar as transformações lineares de forma simultânea, a
depender de seu preenchimento. Por exemplo, a diagonal da matriz pode receber os fatores de escala, enquanto a translação
é expressa na quarta linha.
 
FVector4 original = FVector4(3, 8, 3, 1);
FMatrix transfLin = FMatrix(FVector(2, 0, 0), FVector(0, 0.5, 0),
FVector(0, 0, 3), FVector(0,0,0)).
ConcatTranslation(FVector(10,20,30));
// [[2 0 0 0] [0 0.5 0 0] [0 0 3 0] [10 20 30 1]]
FVector4 modificado = transfLin.TransformFVector4(original);
// [16 24 39 1]
// [x,y,z,1] x [[sx,0,0,0][0,sy,0,0][0,0,sz,0][tx,ty,tz,1]] =
// [x*sx+tx, y*sy+ty, z*sz+tz, 1]
 Listagem: Alteração de escala e translação a partirtravés de matriz 4x4. Fonte: O autor.
A rotação é a transformação linear de maior custo computacional e normalmente utilizamos as notações de Euler ou
Quaternion para gerenciá-la. Enquanto Euler representa as rotações em termos de três valores simultâneos, em torno dos
eixos X, Y e Z, um Quaternion adota uma forma alternativa de construção, que permite incorporar a suavização do
movimento baseada em operação de slerp (Spherical Linear Interpolation), produzindo movimentos mais naturais.
 
FVector euler = FVector(0, 0, 90); // 90 graus em Z
FQuat quat = FQuat::MakeFromEuler(euler);
FVector rotacionado = quat.RotateVector(FVector(0, 2, 0));
// [0, 2, 0] -> [-2, 0, 0]
 Listagem: Rotação de um ponto ao redor do eixo Z. Fonte: O autor.
Comentário
É sempre interessante conhecer as operações algébricas para o correto entendimento de toda a física envolvida na concepção
de um jogo digital. Inicialmente, nem todos os atores estão sujeitos à in�uência da física, sendo aplicável apenas aos que
associam-se a corpos rígidos.
Um corpo rígido, ou RigidBody, recebe a ação de forças sem que ocorra deformação, sendo muito comum em Game Engines,
enquanto SoftBody e Cloth são modi�cados pela ação das forças, permitindo uma simulação de tecidos de grande realismo.
Na Unreal Engine é possível utilizar corpos maleáveis por meio das bibliotecas de acesso ao PhysX, mas, para os processos
que utilizamos aqui, não será necessário chegar nesse nível de complexidade.
 
Quando uma força atua sobre um corpo rígido, será imposta uma aceleração inversamente proporcional à massa
con�gurada, mas apenas se tiver intensidade su�ciente para contrapor o arraste de�nido, algo que em última análise
corresponderia à rugosidade da superfície de contato do objeto. Materiais físicos podem ser utilizados para re�nar as
propriedades físicas do objeto, como densidade, fricção e elasticidade, entre outras.
No ambiente da Unity 3D, a de�nição de um corpo rígido ocorre com o acréscimo explícito de um componente do tipo
RigidBody a um GameObject, mas, na Unreal Engine, basta marcar o atributo Simulate Physics, no painel Details, para um
ator qualquer. Após ativar a simulação física, podemos aplicar as forças por meio de Blueprint ou código C++, e atributos
como massa ou arraste linear, con�gurados na mesma área, que terão impacto direto no resultado.
 
float intensidade = 1000;
UMeshComponent* mesh =
GetOwner()->FindComponentByClass<UMeshComponent>();
mesh->AddForce(FVector(0, intensidade, 0));
 Listagem: Aplicação de força a partir de um ActorComponent. Fonte: O autor.
No fragmento de código é possível observar a aplicação da força em uma malha, a qual deve ser recuperada a partir de
FindComponentByClass, tendo como tipo UMeshComponent. Porém, a malha seria associada ao ator da cena. Logo,
devemos utilizar GetOwner. Como a malha traz o atributo Physics Simulation, ela permite o uso do comando AddForce, que
aplica uma força com intensidade con�gurada a partir dos eixos de um FVector.
Para adicionar força na Unity 3D, utilizaríamos GetComponent,
tendo como tipo RigidBody, e o método para adição de força seria,coincidentemente, AddForce.
Ao aplicar uma força, estamos adicionando aceleração ao objeto, mas ele �ca sujeito ao atrito, desacelerando com o tempo,
efeito que pode ser amenizado diminuindo-se o arraste linear, ou seja, alterando-se o valor de Linear Damping no painel
Details. No entanto, se quisermos de�nir um movimento constante para um objeto qualquer, utilizamos a velocidade linear,
zeramos o valor do arraste linear, para evitar o efeito do atrito, e desativamos a gravidade.
 
void UMover::BeginPlay()
{
Super::BeginPlay();
float velocidade = 50;
UMeshComponent* mesh =
GetOwner()->FindComponentByClass<UMeshComponent>();
mesh->SetPhysicsLinearVelocity(FVector(0, velocidade, 0));
}
 Listagem: Definição da velocidade linear do objeto. Fonte: O autor.
Criando uma classe do tipo ActorComponent, com uso da implementação de BeginPlay do exemplo, efetuando as
con�gurações físicas mencionadas em um componente StaticMesh, com mobilidade Movable, e associando o componente
à classe, veremos que o objeto passa a mover-se para a direita durante a execução do jogo.
Atenção
Lembre-se de que estamos em um ambiente tridimensional, e tanto as velocidades quanto as acelerações são con�guradas
para os três eixos, em componentes do tipo FVector.
Da mesma forma, podemos de�nir uma rotação constante a partir da velocidade angular, lembrando sempre de considerar o
eixo de rotação, ou pivot, do objeto. Quando utilizamos o modo de translação, o gizmo localiza-se junto ao pivot. Para alterar
o pivot de um objeto da cena precisamos arrastar o gizmo com o clique no botão central do mouse junto à tecla ALT, mas
lembrando de salvar a posição escolhida, ao �nal clicando com o botão direito sobre o objeto e escolhendo a opção
Pivot..Set as Pivot Offset.
 
void UMover::BeginPlay()
{
Super::BeginPlay();
float velocidade = 50;
UMeshComponent* mesh =
GetOwner()->FindComponentByClass<UMeshComponent>();
mesh->SetPhysicsAngularVelocity(FVector(0, velocidade, 0));
}
 Listagem: Definição da velocidade angular do objeto. Fonte: O autor.
Devemos lembrar que a interação entre elementos da cena que simulam a física pode gerar reações, fazendo com que os
parâmetros de�nidos sofram alterações em tempo de execução, o que leva à necessidade de travar rotações e translações
em determinados eixos, como em um jogo de nave de visão superior, por meio do qual queremos que elas bloqueiem umas
às outras, mas sem rotacionar os objetos.
Para impedir os efeitos físicos em determinado eixo, basta marcar o eixo em Lock Position ou Lock Rotation, ambos na
propriedade Constraints do setor Physics, em Details.
 Figura: Configuração das características físicas. Fonte: O autor.
Outro elemento importante para a física nos jogos é a colisão, ou seja, áreas e volumes que podem bloquear a passagem de
um objeto sobre outro. É a partir de colisores que impedimos a passagem através de uma parede, ou reconhecemos o
impacto de um projétil.
Diversas con�gurações podem ser efetuadas no setor Collision, do painel Details, incluindo o comportamento do colisor, que
inclui BlockAll para o padrão de bloqueio, ou OverlapAll para a utilização como gatilho simples, ambas opções de Collision
Presets. Além da opção de de�nir os colisores no próprio FBX, como visto em aula anterior, alguns colisores são oferecidos
pela Unreal Engine, como Box Collision, Capsule Collison e Sphere Collision, adicionados a partir do painel Details, no botão
Add Component.
Como o cálculo da colisão, principalmente em ambientes 3D, pode ser bastante custoso, devemos buscar as formas mais
simples, como o uso de colisor cilíndrico no tronco de uma árvore, formato de cápsula para o personagem de primeira
pessoa, ou esférico para uma bola de fogo utilizada como projétil.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
Utilização de forças e colisores
Ao Como já vimos alguns fragmentos de código que exempli�cam o uso de força, em situações genéricas, aqui vamos
compreender a con�guração da física em uma cena completa, com base em elementos de Blueprints. Inicialmente vamos
de�nir um projeto, com base em Blueprints, assumindo o cenário padrão e sem adicionar o Starter Content.
Vamos acrescentar vários elementos do tipo Cube, con�gurados com a ativação da simulação física ativada, organizados
em uma pilha. A pilha de caixas servirá como alvo no lançamento de projéteis a partir do ângulo de visão de um jogador em
primeira pessoa.
Comentário
O uso da tecla ALT junto ao clique, no modo de translação, faz cópias do objeto, permitindo o alinhamento em termos de alguns
dos eixos de forma simples.
Para diferenciar as caixas, crie dois materiais com os nomes Amarelo e Vermelho, em que cada um deverá apresentar a cor
descrita por seu nome. Para de�nir as cores, temos que associar, no Material Editor, o conector Base Color a um nó do tipo
Constant3Vector. Clicando duas vezes sobre o nó utilizaremos os valores RGB corretos para cada cor.
Na Unreal Engine, o padrão RGB utiliza valores reais entre 0 e 1, o
que levaria à adoção de 1, 0, 0 para vermelho, e 1, 1, 0 para amarelo.
Após de�nir os materiais, eles devem ser associados às caixas de forma alternada a partir do atributo Materials de cada
uma. Organizando de forma adequada, formaremos uma pilha de caixas com pequenos espaços, como pode ser observado
a seguir.
 Figura: Cenário para teste de forças e colisões. Fonte: O autor.
Agora precisamos de um componente capaz de interagir com o ambiente. Para tal, vamos adicionar o pacote de FPS,
clicando em Add New, no Asset Browser, e escolhendo a opção Add Feature or Content Pack, seguido da seleção de First
Person, na aba Blueprint. Com o pacote acrescentado ao projeto, vamos apenas modi�car o modo de jogo a partir do painel
World Settings, com a seleção de FirstPersonGameMode em Game Mode Override.
 
Ao atirar nas caixas, elas respondem deslocando-se segundo as regras do motor de física. No entanto, o impacto será muito
forte e, se quisermos um efeito mais realista, podemos alterar a massa das caixas para valores maiores, no atributo
MassInKg, da divisão Physics.
 Figura: Caixas deslocadas com o impacto dos tiros. Fonte: O autor.
Se analisarmos FirstPersonCharacter, presente no diretório Blueprints de FirstPersonBP, poderemos compreender a forma
como o impulso é transmitido para as caixas nas ações de tiro do personagem. Observando o EventGraph do nível Character
Movement, temos o �uxo iniciado em Spawn Projectile, de�nindo a resposta ao botão de tiro, sucedida pelo cálculo da
direção em CalculateAdjustedDirection, a veri�cação de um alvo viável na direção calculada em TraceShot e, �nalmente, a
aplicação do impulso no alvo em Deal With Impact.
 Figura: Trecho do Blueprint com adição de impulso devido ao tiro. Fonte: O autor.
Apesar de termos um tiro de�nido, não temos, no modelo original, a imagem de um projétil, mas criaremos uma versão
modi�cada com a representação visual. Inicialmente faremos a cópia de FirstPersonCharacter para o diretório Content,
modi�cando o nome do Asset para FirstPersonModi�cado, e excluindo do �uxo de execução os grupos
CalculateAdjustDirection, TraceShot e Deal With Impact a partir do EventGraph de Character Movement, ou seja, será
mantido apenas o reconhecimento da ação de tiro e resgate do ângulo de visão.
Para de�nir o projétil, vamos acrescentar o pacote padrão Twin Stick Shooter, de acordo com o mesmo procedimento
adotado para First Person. O Blueprint do projétil estará no diretório Blueprints do pacote TwinStickBP, com o nome
TwinStickProjectile, e deve ser copiado para o diretório Content, com o nome FirstPersonProjectile.
 Figura: Visão do Content Browser com os componentes do projeto. Fonte: O autor.
Com os recursos necessários disponíveis vamos editar FirstPersonModi�cado e começar a construir o �uxo de construção
do projétil com a de�nição das coordenadas para a geração, considerando a posição do personagem e a distância
necessária para que apareça logo após o cano da arma. O cálculo da posição incluium deslocamento maior ou igual ao
tamanho da arma, na direção para onde o personagem aponta, a partir de sua localização.
 
Inicialmente obtemos o componente Transform do personagem, com Get Actor Transform, e o dividimos nos atributos de
translação, rotação e escala, acrescentando um Break Transform, enquanto a direção observada é obtida com Get Actor
Forward Vector, sendo multiplicada por 50, de forma a de�nir o deslocamento que será adicionado à posição resgatada.
Note que o nó de multiplicação é do tipo Vector * Float, enquanto o de soma é do tipo Vector + Vector.
 Figura: Cálculo da posição para geração do projétil. Fonte: O autor.
A rotação do projétil será obtida a partir do conector Rotation, de Get Player View Point, o qual já encontra-se disponível no
grupo Spawn Projectile, enquanto a escala será a mesma do Transform obtido a partir do ator. Com as informações
necessárias, podemos montar um novo componente Transform a partir de um nó do tipo Make Transform.
 Figura: Composição do componente Transform para geração do projétil. Fonte: O autor.
Com a montagem do Transform acrescentamos um nó do tipo Spawn Actor from Class, com a escolha de First Person
Projectile para Class, seguido da associação do Transform gerado ao conector Spawn Transform. Adicionamos nosso novo
nó ao �uxo de execução original, como sucessor de Get Player View Point, e já temos a geração de projéteis ao atirar,
embora ainda não possa ser percebida, devido às atuais características do projétil em si.
 Figura: Configuração para geração do projétil no fluxo de execução. Fonte: O autor.
Antes de iniciar a con�guração do projétil, podemos ter um retorno em modo texto durante a execução, acrescentando um nó
do tipo Print Text. Os nós para impressão de texto são uma boa ferramenta para acompanhar valores calculados durante a
execução do jogo, e costumam ser utilizados pelos desenvolvedores de jogos para testar funcionalidades que ainda estão em
processo de desenvolvimento, ou, ainda, apresentar informações relevantes para o jogador, já com o jogo completo, como na
troca de mensagens entre jogadores.
 
Vamos apresentar as coordenadas utilizadas para a geração do projétil, conectando a saída da soma vetorial com o conector
InText, mas observando que um nó de conversão de vetor para texto será gerado de forma automática. Também podemos
escolher uma cor para o texto que será exibido, no atributo Text Color. No caso, utilizaremos RGB 1,1,0, ou seja, amarelo.
A execução da impressão do texto deverá ocorrer após a geração do projétil, ou seja, devemos associar Print Text como
sucessor de Spawn Actor.
 Figura: Impressão das coordenadas de geração do projétil. Fonte: O autor.
Ainda falta con�gurar FirstPersonProjectile, onde serão modi�cados poucos atributos, pois o �uxo de execução, com adição
de impulso equivalente à velocidade multiplicada por 20, quando ocorre o contato com um objeto com física ativada, será o
su�ciente para o nosso teste.
 
Selecionaremos o nível de ProjectileMovement, na aba Components, e selecionaremos a opção Should Bounce, no grupo
Projectile Bounces, do painel Details, fazendo com que o projétil seja rebatido pelas malhas sem física con�gurada. Ao
mesmo tempo em que adicionamos o rebatimento, vamos desmarcar a opção Constraint to Plane, no grupo Planar
Movement, pois ela é voltada para jogos em visão superior, restringindo o movimento ao plano.
 Figura: Configuração dos atributos de FirstPersonProjectile. Fonte: O autor.
Embora já esteja funcional neste ponto, os tiros não estão alinhados com o cano da arma, o que exigirá outra pequena
modi�cação, agora em FirstPersonModi�cado. Precisamos alterar, ao nível de Mesh1P, os valores para o grupo Transform,
com os valores -6.6, 2.4 e -156, para os campos X, Y e Z de Location, além de de�nir o componente Z de Rotation com o valor
-20.
 Figura: Posicionamento da malha de FirstPersonModificado. Fonte: O autor.
O modo de jogo já está selecionado como FirstPersonGameMode, mas devemos con�gurar o atributo HUD Class como
None, e Default Pawn Class como FirstPersonModi�cado. A mira será eliminada e a geração dos projéteis já pode ser
testada. Aqui sugerimos a alteração da iluminação para um ambiente mais escuro, obtendo um retorno visual muito mais
rico.
 Figura: Teste da execução com projéteis e configurações necessárias. Fonte: O autor.
Tratamento da colisão
Em termos simples, a função primária de um colisor é de�nir uma área ou volume que impede a sobreposição de objetos no
ambiente de jogo, mas vai muito além disso. A partir de rotinas criadas via linguagens de programação ou �uxos visuais,
personalizamos a resposta padrão do bloqueio, efetuando ações como a destruição do objeto.
Ou, ainda, podemos utilizar o modo de gatilho nos colisores, onde não ocorre o bloqueio, mas apenas o reconhecimento do
outro objeto, como na recarrega de combustível do clássico jogo River Raid, ou nos marcadores de aceleração existentes em
pistas de diversos jogos de corrida.
Normalmente temos poucos eventos relacionados ao controle de colisão nas Game Engines, como ocorrência de bloqueio,
ou entrada e saída da região de gatilho. Embora haja diferenças tecnológicas, os modelos adotados pela Unity 3D e pela
Unreal Engine são bem semelhantes.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
Evento Método da Unity 3D Evento da Unreal Engine
Ocorrência de bloqueio OnCollisionEnter On Component Hit
Entrada em gatilho OnTriggerEnter On Component Begin Overlap
Saída de gatilho OnTriggerExit On Component End Overlap
 Tabela: Tratamento de colisão na Unity 3D e na Unreal Engine. Fonte: O autor.
Para começar nossos estudos acerca do tratamento de colisão, vamos transformar a caixa no centro de nossa pilha em um
Blueprint, o que é feito com o clique em Blueprint/Add Script, no painel Details. Na janela que se abrirá, preenchemos o nome
do Blueprint com Cube_BP e selecionamos as opções New Subclass e Static Mesh Actor.
O novo Blueprint poderá ser observado no Content Browser, e o ator original será substituído por uma instância de Cube_BP.
Para gerar outras instâncias, basta arrastar o Blueprint para a cena, com o reaproveitamento de todas as con�gurações
originais, de forma bastante similar ao modelo de Prefabs oferecido pela Unity 3D.
 Figura: Conversão para Blueprint e ícone apresentado no Content Browser. Fonte: O autor.
Agora podemos editar o Blueprint gerado, de forma a remover o objeto quando ocorrer uma colisão com algum projétil.
Vamos abrir o editor com o duplo clique sobre o ícone e adicionar o evento de colisão por bloqueio, selecionando o nível de
StaticMeshComponent na árvore de componentes. Em seguida, ir até o painel Details, no grupo Events, e clicar sobre o botão
ao lado do evento On Component Hit, o que fará com que seja adicionado ao EventGraph.
 Figura: Adição do evento On Component Hit ao EventGraph do Blueprint. Fonte: O autor.
O conector Other Actor do novo evento indica qual ator colidiu com a caixa, onde devemos extrair a classe dele a partir de um
nó do tipo GetClass e comparar com a classe do projétil, por meio de um nó do tipo Equal (Class). Adicionamos também um
nó do tipo Branch, que deve receber a comparação no conector Condition. Se o resultado for verdadeiro, o �uxo precisa ser
direcionado para um nó do tipo DestroyActor.
 Figura: Fluxo para a remoção do ator na colisão com o projétil. Fonte: O autor.
Executando novamente nosso exemplo, poderemos observar que as caixas que são baseadas no Blueprint mudam o
comportamento padrão do simples deslocamento, sendo removidas da cena quando ocorre a colisão com o projétil.
Agora vamos restringir o número de tiros do jogador e de�nir um volume que irá recarregar a arma na passagem sobre ele.
Inicialmente devemos alterar FirstPersonModi�cado, com o acréscimo de uma variável pública inteira, adotando o nome
Tiros e valor inicial 10.
Após a criação da variável vamos obter o valor de Tiros, acrescentar um nó para a comparação maior do que zero, e liberar o
�uxonatural de tiro apenas se a condição for verdadeira. Para o controle do �uxo, adicionamos um nó do tipo Branch,
relocamos os dois �uxos de entrada de Montage Play, no grupo Spawn Projectile, para o Branch, e conectamos o �uxo do
resultado True do Branch à entrada de Montage Play.
 Figura: Fluxo de controle para liberação da ação de tiro. Fonte: O autor.
Também devemos diminuir a quantidade de tiros disponíveis, o que deve ser feito logo após o teste, devido ao paralelismo
natural do ambiente. Precisaremos de um nó de subtração de inteiros para decrementar uma unidade de Tiros e atribuir o
novo valor no �uxo, além de um nó do tipo Append para a montagem da frase que será exibida via Print String,
concatenando a expressão "Tiros Disponíveis" com o valor de Tiros.
Efetuamos, então, uma nova alteração no �uxo de Spawn Projectile, conectando a saída de Branch com Set, seguido de
Print String, e chegando �nalmente a Montage Play. Note que o decréscimo do valor de Tiros ocorrerá apenas quando o
valor for maior do que zero.
 Figura: Fluxo completo para o controle da quantidade de tiros. Fonte: O autor.
Precisamos de algum processo para recarregar a arma e vamos iniciá-lo com a criação de um marcador, adicionando um
Cone, e a ele, a partir de Add Component do painel Details, uma luz do tipo PointLight, deslocada para a parte superior do
cone, com uso da cor azul, que é escolhida no atributo Light Color, do grupo Light.
 Figura: Criação do marcador de recarga. Fonte: O autor.
Após de�nir o marcador precisamos efetuar o reconhecimento da proximidade do jogador, o que será feito com o acréscimo
de um elemento do tipo Box Trigger, presente no grupo Basic, do painel Place Actors, mesmo local onde Cone é encontrado.
O volume do gatilho deve ser posicionado rente ao solo, envolvendo o cone de marcação e com espaço su�ciente para que o
jogador se aproxime, o que pode ser con�gurado a partir da escala.
Os atores do tipo Trigger precisam ser tratados ao nível do Level Blueprint, acessado a partir da Toolbar, na opção
Blueprints..Open Level Blueprint. O �uxo tratado engloba o jogo como um todo, de�nindo ações globais e o tratamento de
volumes para detecção de colisão, o que iniciaremos com o clique do botão direito e escolha de Add Event for Trigger Box,
seguido da opção Collision e Add On Actor Begin Overlap.
 Figura: Adição do evento para tratamento da passagem pelo Trigger Box. Fonte: O autor.
Com o evento de�nido, adicionamos um nó do tipo Get Player Pawn, seguido da conversão de�nida via Cast To
FirstPersonModi�cado, que deve ocorrer a partir do evento, e arrastando o conector As FirstPersonModi�cado escolhemos
Set para Tiros, com valor 10. O comando de Set é incorporado ao �uxo e, como sucessor, iremos acrescentar um nó do tipo
Print String, com o texto "Arma Recarregada", na cor vermelha.
 Figura: Fluxo de execução para recarga da arma. Fonte: O autor.
O jogo já pode ser executado, com a restrição do número de tiros e recarga a partir do gatilho, além da exibição de
mensagens em modo texto para informar o jogador.
Também é possível programar a resposta para as colisões em linguagem C++, como iremos veri�car a partir da criação de
um ActorComponent, cujo nome será Colisao, em que ocorrerá o reconhecimento da malha e associação do evento ao nível
do código. No arquivo header teremos apenas uma referência interna para a malha, uma propriedade para receber o Blueprint
do projétil, com o nome ProjectileClass, e os métodos BeginPlay e OnHit — este último para o tratamento da colisão.
 
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class COLISAO001_API UColisao : public UActorComponent
{
GENERATED_BODY()
UStaticMeshComponent* mesh;
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite)
TSubclassOf<AActor> ProjectileClass;
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
UPrimitiveComponent* OtherComp, FVector NormalImpulse,
const FHitResult& Hit);
protected:
virtual void BeginPlay() override;
};
 Listagem: Arquivo de cabeçalho para UColisao. Fonte: O autor.
Quanto ao arquivo de implementação, no método BeginPlay temos a captura da malha, com base em
FindComponentByClass, e a associação do evento OnComponentHit com o método OnHit. Já no método OnHit, efetuamos
o teste para identi�car se OtherActor é um projétil. Em caso positivo, utilizamos AddOnScreenDebugMessage para exibir a
mensagem de que foi removido e efetuamos a remoção do ator, com a chamada para Destroy.
 
void UColisao::BeginPlay()
{
Super::BeginPlay();
mesh = GetOwner()->FindComponentByClass<UStaticMeshComponent>();
mesh->OnComponentHit.AddDynamic(this, &UColisao::OnHit);
}
void UColisao::OnHit(UPrimitiveComponent* HitComp,
AActor* OtherActor, UPrimitiveComponent* OtherComp,
FVector NormalImpulse, const FHitResult& Hit)
{
if (OtherActor != NULL && OtherActor != GetOwner() &&
OtherActor->IsA(ProjectileClass))
{
GEngine->AddOnScreenDebugMessage(
-1, 5.f, FColor::Red, TEXT("Removido"));
GetOwner()->Destroy();
}
}
 Listagem: Implementação da classe UColisao. Fonte: O autor.
Em nosso último passo precisamos apenas adicionar Colisao a uma caixa comum, associar o Blueprint a
FirstPersonProjectile, no atributo Projectile Class, e ativar a colisão, marcando a opção Simulation Generates Hit Events
ao nível da malha estática. Podemos executar o jogo, veri�cando o efeito programado para a colisão e a mensagem para o
jogador.
 Figura: Versão final do exemplo e configurações para uso de UColisao. Fonte: O autor.
Atividade
1. A utilização do mecanismo de física, dentro de qualquer Game Engine, requer conhecimento acerca de alguns princípios
matemáticos, como as operações da álgebra linear. Por exemplo, para alterar a escala de uma malha, qual operação deverá ser
executada sobre seus vértices?
a) Multiplicação entre Vetores.
b) Soma Vetorial.
c) Interpolação Linear Esférica.
d) Multiplicação de Vetor por Escalar.
e) Subtração Vetorial.
2. A partir da Unreal Engine temos um ambiente muito �exível para con�gurar o uso de forças por meio de programação em
C++ ou via Blueprints. No �uxo de execução de um Blueprint, se quisermos aplicar uma força pontual a um objeto da cena,
como ocorre no contato de um projétil com seu alvo, qual seria o tipo de nó mais adequado?
a) Add Impulse at Location.
b) Blend Poses by Int.
c) Get Player View Point.
d) Is Simulating Physics.
e) Add Actor Local Rotation.
3. Os dois comportamentos possíveis para os colisores são bloqueio e gatilho, em que o primeiro impede a passagem de um
objeto sobre o outro e o segundo não. Quando queremos detectar o contato de um segundo objeto, dentro da funcionalidade de
bloqueio, qual evento deverá ser tratado no código C++ ou no �uxo do Blueprint?
a) OnTrigerEnter.
b) OnComponentBeginOverlap.
c) OnComponentHit.
d) OnTriggerExit.
e) OnComponentEndOverlap.
Notas
Bones1
São criadas as chaves de animação, ao longo da linha de tempo, para os diversos componentes da hierarquia, e a malha é
aplicada sobre ela, adequando-se ao movimento esperado — como ocorre para nós, quando nossos esqueletos se movem e a
pele segue o movimento que foi imposto.
Referências
CARNALL, B. Unreal Engine 4.X By Example. Birmingham: Packt Publishing, 2016.
COPLE, D. Desenvolvimento de Jogos II. Rio de Janeiro: SESES, 2019.
DUNN, F.; PARBERRY, I. 3D Math Primer for Graphics and Game Development. Texas: Wordware Publishing, Inc., 2002.
MONIEM, M. Mastering Unreal Engine 4.X. Birmingham: Packt Publishing, 2016.
SATHEESH, P. Unreal Engine 4 Game Development Essentials. Birmingham: Packt Publishing, 2016.
SHERIF, W.; WHITTLE, S. Unreal Engine 4 Scripting with C++ Cookbook. Birmingham: Packt Publishing, 2016.
Próxima aula
Ferramentas para criação de áudio;
Sonorização de jogos na Unreal Engine;
Malhas de navegação e som espacial.
Explore mais
No site 3D Game Engine Programming leia sobre os fundamentos matemáticos para a de�nição de Quaternions.
Em Unreal Engine consulte a referência da Unreal Engine sobre o motorde física.
Em raywenderlich leia sobre a construção de FPS muito simples, com controle de colisão e de dano.
javascript:void(0);
javascript:void(0);
javascript:void(0);