Baixe o app para aproveitar ainda mais
Prévia do material em texto
Desenvolvimento de Jogos Digitais II Aula 5: Programação e Interatividade Apresentação A maioria das Game Engines permite a personalização de funcionalidades a partir de alguma linguagem de programação, e no caso da Unreal Engine, a linguagem C++ é utilizada como base para o desenvolvimento. Mesmo os diversos componentes dos Blueprints foram criados nesse ambiente, fato que justi�ca a plena compatibilidade entre os ferramentais, o que permite a de�nição da interatividade e regras do jogo de forma �exível e robusta. Objetivo Analisar a sintaxe básica da linguagem C++; Construir componentes para a Unreal Engine utilizando C++; Demonstrar o uso de C++ para o controle de dispositivos de entrada. Sintaxe C++ Um elemento essencial em qualquer Game Engine é a possibilidade de expandir e adaptar funcionalidades com base em alguma linguagem de programação. Considerando-se os dois exemplos mais populares do mercado de jogos, enquanto a Unity 3D utiliza C#, na Unreal Engine adotamos o C++ como padrão para desenvolvimento. A linguagem C++ é predecessora do C#, tendo servido como base de sua sintaxe. O uso de uma linguagem clássica e de grande abrangência na área cientí�ca, como o C++, permite acesso a uma grande base de algoritmos já implementados para áreas críticas nos jogos, como otimizações grá�cas e sistemas de inteligência arti�cial. De forma simplista, podemos interpretar o C++ como a linguagem C orientada a objetos, mas existem diversas outras melhorias, como a sintaxe de ponteiros com o uso de new e delete, no lugar das diversas funções de alocação de memória do C. Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online #include <iostream> using namespace std; main() { cout << "Exemplo Simples" << endl; return 0; } Listagem: Exemplo simples programado em C++. Fonte: O autor. Nosso primeiro exemplo demonstra algumas características do C++, como o uso de include para a importação de bibliotecas, o início da execução na função main e a saída texto no vídeo por meio de cout. Comentário Uma observação é a de que o uso do namespace std impede que tenhamos de escrever std::cout no lugar de cout. A linguagem é fortemente tipada, exigindo que a variável seja associada a um tipo especí�co, e temos apenas um pequeno conjunto de tipos nativos. Também é necessário prestar atenção ao uso de letras maiúsculas e minúsculas, já que a linguagem é case sensitive. Tipo Nativo Limites e Observações Int Variável inteira, variando de -2.147.483.648 até 2.147.483.647 float Variável de ponto flutuante, variando de -3,402E38 até 3,402E38 double Variável de ponto flutuante, variando de -1,797E308 até 1,797E308 char Caractere do padrão ASCII wchar_t Caractere do padrão UTF-16 bool Variável do tipo lógico, assumindo os valores true ou false Tabela: Tipos nativos da linguagem C++. Fonte: O autor. Vários desses tipos podem ser modi�cados utilizando-se as palavras-chave signed, unsigned, short e long. Quando um desses modi�cadores é usado sem a de�nição do tipo de dado, o compilador assume o tipo int. Tipo Nativo Limites e Observações short int Modificação dos limites de int para -32.768 e 32.767 unsigned short int Modificação dos limites de int para 0 e 65.535 unsigned long int Modificação dos limites de int para 0 e 4.294.967.295 unsigned char Modificação dos limites numéricos de char para 0 e 255 long float Modificação dos limites de float para os de double Tabela: Modificadores de tipos na linguagem C++. Fonte: O autor. A sintaxe do C++ lembra muito a utilizada no C#, até mesmo pela origem comum, mas algumas diferenças podem ser observadas com relação ao uso de memória, principalmente no que se refere à utilização de ponteiros em C++. #include <iostream> using namespace std; main() { int a = 5; int* b = &a; // b aponta para o endereço de a *b = 10; // posição apontada por b recebe 10 cout << a << endl; // imprime o valor 10 return 0; } Listagem: Utilização básica de ponteiros no C++. Fonte: O autor. Além dos tipos básicos, é possível criar tipos compostos em C++ com o uso da palavra reservada struct. Alguns livros de�nem o tipo struct como uma espécie de classe simples, mas isso não é totalmente correto, pois já existia na linguagem C, que não é orientada a objetos. Struct Jogador { string nome; int pontos; } Jogador j1; j1.nome = “Luiz”; j1.pontos = 1320; Listagem: Definição e uso de tipos compostos. Fonte: O autor. Em termos de operadores e controle de �uxo, não existe diferença para as demais linguagens derivadas do C. Podemos observar, no exemplo seguinte, as estruturas de controle de �uxo for e if sendo utilizadas, além do cin para entrada de dados. #include <iostream> using namespace std; main() { int soma = 0, b; for (int a = 1; a <= 10; a++) { cout << “Digite um número:”; cin >> &b; if (b%2 == 0) soma += b; } cout << “A soma dos pares será “ << soma << endl; return 0; } Listagem: Exemplo com entrada e saída no C++. Fonte: O autor. Algo bastante diferente entre o C# e o C++ é a necessidade de arquivos header no C++. Eles guardam apenas as assinaturas de funções e classes que serão implementadas no arquivo cpp de nome equivalente, permitindo a importação a partir de outros arquivos de código-fonte. [calculadora.h] int somar(int a, int b); [calculadora.cpp] #include “calculadora.h” int somar(int a, int b) { return a + b; } Listagem: Arquivo header e arquivo de implementação. Fonte: O autor. Você pode observar, nos códigos apresentados, que apesar de trazer todo o ferramental necessário para a implementação orientada a objetos, o C++ não exige que seja feito dessa forma. De qualquer maneira, como a Unreal Engine trabalha dentro de um ambiente orientado a objetos, é necessário compreender a sintaxe utilizada pelo C++ na de�nição de classes e objetos. Inicialmente as classes podem ser prototipadas em arquivos header, com a de�nição de atributos e métodos, sempre considerando os níveis de acesso private, public e protected. [escritorio.h] class Pessoa{ private: int matricula; string nome; public: Pessoa(int matricula, string nome); ~Pessoa(); void exibir(); } Listagem: Protótipo da classe Pessoa, criado no arquivo escritorio.h – Fonte: O autor. Em seguida, as classes são implementadas no arquivo cpp, onde aparece o operador de resolução de escopo (duplo dois pontos). Esse mesmo operador é utilizado na chamada de métodos estáticos, ou seja, aqueles que não precisam de uma instância para que sejam executados. [escritorio.cpp] #include <iostream> #include "escritorio.h" using namespace std; Pessoa::Pessoa(int matricula, string nome){ this -> matricula = matricula; this -> nome = nome; } Pessoa::~Pessoa(){ cout << nome + " removido." << endl; } void Pessoa::exibir(){ cout << nome << " tem " << idade << " ano(s)." << endl; } Listagem: Implementação da classe Pessoa, efetuada no arquivo escritorio.cpp – Fonte: O autor. É interessante observar o uso do ponteiro de autorreferência this no construtor, o que viabiliza a diferenciação entre o atributo do objeto, precedido do ponteiro, e o argumento que foi recebido no construtor, quando esses dois apresentam o mesmo nome. Na linguagem C++ é possível utilizar os objetos como variáveis comuns ou como ponteiros, mas, de forma diferente do que ocorre em linguagens como o Java, no C++ não existe um ferramental para coleta de lixo, e todo objeto alocado dinamicamente deve ser removido de forma explícita na programação. A alocação é efetuada com o uso do operador new, sendo acionado o construtor adequado, a partir dos parâmetros utilizados, e a remoção ocorre com a utilização do operador delete, podendo ser de�nido um método destrutor para que seja executado algum procedimento imediatamente antes de desalocar o objeto. Pessoa p1("Ana",25); p1.exibir(); Pessoa* p2 = new Pessoa("Marcos",36); p2 -> exibir(); delete(p2); Listagem: Alocação, utilização e remoção do objeto na linguagem C++. Fonte:O autor. Na linguagem C++ é possível utilizar os objetos como variáveis comuns ou como ponteiros, mas, de forma diferente do que ocorre em linguagens como o Java, no C++ não existe um ferramental para coleta de lixo, e todo objeto alocado dinamicamente deve ser removido de forma explícita na programação. A alocação é efetuada com o uso do operador new, sendo acionado o construtor adequado, a partir dos parâmetros utilizados, e a remoção ocorre com a utilização do operador delete, podendo ser de�nido um método destrutor para que seja executado algum procedimento imediatamente antes de desalocar o objeto. Pessoa p1("Ana",25); p1.exibir(); Pessoa* p2 = new Pessoa("Marcos",36); p2 -> exibir(); delete(p2); Listagem: Alocação, utilização e remoção do objeto na linguagem C++. Fonte: O autor. Em termos de herança, a linguagem C++ permite diferentes combinações com relação ao nível de acesso dos membros originais. Uma herança de�nida como pública mantém os níveis originais, enquanto uma herança privada faz com que os membros herdados nos níveis público e protegido transformem-se em privados na nova classe. Class Funcionario: public Pessoa{ private: string trabalho; public: Funcionario(int matricula, string nome, string trabalho): base(matricula,nome) { this -> trabalho = trabalho; } void exibir() { Pessoa::exibir(); cout << “ e trabalha como “ < trabalho << endl; } } Listagem: Definição de uma classe descendente, com implementação direta. Fonte: O autor. Note que aqui não foi utilizada a prototipação, ocorrendo a implementação direta, o que pode ser feito quando visamos apenas a utilização local da classe. Vale lembrar que os arquivos header não permitem implementações, o que faz com que o código nesse estilo deva estar em um arquivo cpp, que não pode ser importado. Comentário Também é interessante observar que o construtor de Funcionario inicialmente chama o construtor de Pessoa com o uso da palavra base, e que um método do pai que tenha sido sobrescrito (polimor�smo) deve ser acessado com o nome da classe original, seguido do operador de resolução de escopo. Com relação à de�nição de propriedades, não existe no C++ uma sintaxe voltada para isso, como ocorre no C#, mas é utilizado o padrão de métodos getters e setters, a exemplo de linguagens como Java. Class Funcionario: public Pessoa{ private: string trabalho; public: /* Métodos anteriores omitidos */ string getTrabalho() { return trabalho; } void setTrabalho(string trabalho) { this -> trabalho = trabalho; } } Listagem: Utilização de getters e setters na definição de uma propriedade. Fonte: O autor. Uso de C++ na Unreal Engine A forma mais simples de utilizar a linguagem C++ na Unreal Engine é a partir da criação de um projeto apropriado. Você deve escolher a guia C++, e dentro dela optar pelo tipo Basic Code, digitando o nome do projeto, como Teste001R, e de�nindo o diretório de base. Figura: Criação de projeto simples com base em C++, na Unreal Engine 4.21 – Fonte: O autor. Em versões mais recentes da Unreal Engine, escolhemos novo projeto de Games, tipo Blank, e apenas na última tela é escolhido o modelo C++. As outras con�gurações disponíveis incluem qualidade grá�ca e plataforma de execução. Figura: Escolha do modelo de projeto com base em C++, na Unreal Engine 4.25 – Fonte: O autor. Após a criação do projeto, basta acionar a opção Add New no Content Browser e selecionar New C++ Class. Em seguida será solicitado o tipo da superclasse, que deverá ser Actor para este exemplo. Clicando em Next deverá ser preenchido o nome da nova classe como Rotacao, tendo também a opção de escolher o diretório ou manter a opção padrão. Figura: Seleção do ascendente e nomeação da classe. Fonte: O autor. A classe Actor serve de base para os componentes que podem ser adicionados às cenas da Unreal Engine, assumindo papel similar ao do GameObject, presente no ambiente da Unity 3D. As demais opções lidam com elementos mais especializados, como Pawn, um ator que interage com controladores, e Character, especialização de Pawn que consegue andar pelo ambiente, entre diversas outras. Agora você poderá visualizar a classe ARotacao e seu arquivo header no ambiente do Visual Studio, por meio do do Solution Explorer (Gerenciador de Soluções). Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online Inicialmente, você deve observar a de�nição da nova classe, no header, onde ocorre a especialização pública de AActor, com a de�nição do construtor, além dos métodos polimór�cos BeginPlay e Tick, devendo ser acrescentado o atributo público velocidade, do tipo �oat. O método BeginPlay é chamado no início do jogo, ou quando o Actor é gerado (spawned), enquanto Tick é chamado a cada novo frame. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Rotacao.generated.h" UCLASS() class TESTE001R_API ARotacao : public AActor { GENERATED_BODY() public: ARotacao(); protected: virtual void BeginPlay() override; public: virtual void Tick(float DeltaTime) override; float velocidade = 0.2f; }; Listagem: Arquivo header da classe ARotacao. Fonte: O autor. Nas classes geradas para o ambiente da Unreal Engine, algo muito particular e importante são os metadados de especi�cação, que funcionam como elementos comportamentais, sendo reconhecidos pela Game Engine e voltados para a integração com o ambiente. No arquivo de cabeçalho podemos observar o metadado UCLASS, além da macro GENERATED_BODY. Metadado Utilização GENERATED_BODY Macro que define toda a infraestrutura necessária para a comunicação com a Game Engine no protótipo da classe. UCLASS Define a classe como um elemento interativo da Unreal Engine. UENUM Define o enumerado como um elemento interativo da Unreal Engine. UFUNCTION Configura o método como uma função que pode ser reconhecida ao nível dos Blueprints. UINTERFACE Define a interface como um elemento interativo da Unreal Engine. UPROPERTY Transforma o atributo em uma propriedade editável, que pode ser modificada no painel Details ou em Blueprints. USTRUCT Define o registro como um elemento interativo da Unreal Engine. Tabela: Metadados e macros comuns da especificação da Unreal Engine. Fonte: O autor. Agora que temos a classe prototipada adequadamente, devemos codi�car o comportamento desejado no arquivo de implementação. No caso, será de�nida uma rotina que rotaciona a �gura em torno de um eixo, invertendo o sentido do movimento entre os limites de 0° e 180°. #include "Rotacao.h" ARotacao::ARotacao() { PrimaryActorTick.bCanEverTick = true; } void ARotacao::BeginPlay() { Super::BeginPlay(); } void ARotacao::Tick(float DeltaTime) { Super::Tick(DeltaTime); FTransform transf1 = GetActorTransform(); FQuat rot1 = transf1.GetRotation(); float angulo = rot1.GetAngle() + DeltaTime * velocidade; if (angulo > 3.14 || angulo < 0) velocidade *= -1; FQuat quat1 = FQuat(FVector::ForwardVector, angulo); SetActorRotation(quat1); } Listagem: Implementação da classe ARotacao. Fonte: O autor. Inicialmente é capturado o componente FTransform do Actor e, a partir dele, é obtido o atributo FQuat (Quaternion) referente à rotação atual. Em seguida é calculado o ângulo de rotação, tendo como base o ângulo atual, acrescido da velocidade angular em radianos multiplicada pelo DeltaTime. O tempo delta mede o período que decorre entre dois frames subsequentes e visa manter a velocidade de atualização equivalente entre máquinas distintas. Atenção Devido às características do Quaternion, ocorre a inversão do movimento entre os limites de 0° e 180°. Para manter o sentido da rotação, a velocidade deve ser invertida quando os limites são atingidos. Ao �nal, o Quaternion contendo o eixo e ângulo de rotação, com o nome quat1, é de�nido, sendo aplicado ao Actor a partir de SetActorRotation. Note que o eixo de rotação utilizado é FVector::ForwardVector, equivalente ao eixo X, causando o giro no plano YZ. Comentário Como você deve terobservado, o nome da classe, na Unreal Engine, recebe uma letra A no início, constituindo um padrão de nomenclatura para o ambiente. Agora que tudo está pronto, podemos compilar a solução no Visual Studio, a partir da opção Compile..Build Solution, ou no próprio ambiente da Unreal Engine, com a opção Compile. Figura: Classe ARotacao, no Content Browser, e objeto Rotacao1, no painel Details. Fonte: O autor. Com tudo preparado você poderá iniciar o jogo, com a utilização da opção Play, sendo possível observar o cubo rotacionado no ar enquanto efetua um passeio pelo ambiente 3D. Figura: Teste da classe ARotacao, com a execução do projeto. Fonte: O autor. Controle de Dispositivos de Entrada Para capturar as entradas efetuadas pelo jogador vamos precisar de uma classe descendente de Pawn, que caracteriza o tipo de ator mais simples com capacidade de aceitar a interação com o ambiente. A nova classe receberá o nome Movimento e contará com uma câmera para acompanhamento da malha estática, cujo posicionamento será controlado via teclado. Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online Figura: Escolha do tipo Pawn na definição da classe. Fonte: O autor. Inicialmente devemos con�gurar o uso de dispositivos de entrada em nosso projeto, pois, no ambiente da Unreal Engine, todos os controles utilizados devem ser mapeados. Com o uso do menu Edit..Project Settings, na divisão Engine..Input da janela de con�gurações, obteremos acesso ao painel de mapeamento de entradas, que podem ser de dois tipos principais: Action Mappings, voltado para o funcionamento discreto das teclas, e que dão suporte aos eventos IE_Pressed, IE_Released ou IE_Repeated; Axis Mappings, utilizado para entradas contínuas, como os eixos de um joystick. Utilizaremos o controle via teclado e de�niremos o mapeamento Tecla_Z apontando para Z, no grupo key, e Tecla_X, apontando para X. Ao nível do código C++ teremos a ligação entre cada mapeamento com os eventos IE_Pressed, para tecla pressionada, e IE_Repeated, quando a tecla é mantida abaixada. Figura: Mapeamento de entradas para o exemplo. Fonte: O autor. Além de viabilizar o uso de diversos tipos de dispositivos, inclusive para consoles, como Play Station e Xbox, é possível combinar as entradas selecionadas com um conjunto de teclas de controle, como Shift, Ctrl e Alt. No código do arquivo header temos a prototipação da classe AMovimento, descendente de Apawn, quando poderemos observar, além do construtor, BeginPlay e Tick, já utilizados na classe Rotacao, o método SetupPlayerInputComponent, que será utilizado para efetuar a ligação entre os mapeamentos da entrada e os métodos de reposta interno, no caso TeclaZ_Mantida e TeclaX_Mantida. Teremos também duas propriedades, voltadas para a con�guração da velocidade e da malha estática, além de um atributo interno para o sentido da translação. UCLASS() class TESTE003R_API Amovimento : public Apawn { GENERATED_BODY() public: Amovimento(); protected: virtual void BeginPlay() override; public: virtual void Tick(float DeltaSeconds) override; // Ligação dos mapeamentos com os métodos internos virtual void SetupPlayerInputComponent( class UinputComponent* InputComponent) override; void TeclaZ_Mantida(); void TeclaX_Mantida(); UPROPERTY(EditAnywhere) UsceneComponent* Malha; UPROPERTY(EditAnywhere) float Velocidade = 150.0f; private: int multiplica = 0; }; Listagem: Arquivo header da classe AMovimento. Fonte: O autor. Após a de�nição do header, precisamos implementar as funcionalidades de nossa classe no arquivo Movimento.cpp, onde temos inicialmente o construtor padrão. AMovimento::AMovimento() { PrimaryActorTick.bCanEverTick = true; // Direciona o controle para o primeiro jogador AutoPossessPlayer = EAutoReceiveInput::Player0; RootComponent = CreateDefaultSubobject<USceneComponent>( TEXT("RootComponent")); UCameraComponent* OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera")); Malha = CreateDefaultSubobject<UStaticMeshComponent>( TEXT("Malha")); // A câmera é posicionada para visualização correta da malha OurCamera->SetupAttachment(RootComponent); OurCamera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f)); OurCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f)); Malha->SetupAttachment(RootComponent); Listagem: Primeiro trecho do arquivo Movimento.cpp – Fonte: O autor. Analisando o código, ocorre o acionamento dos eventos a cada quadro, como em Rotacao, e a captura da entrada associada ao primeiro jogador, por meio de AutoPossessPlayer. Temos em seguida a construção dos atores associados, com RootComponent de�nindo a referência na cena, OurCamera representando a câmera, e Malha de�nindo o objeto visual, o que é feito a partir do método CreateDefaultSubobject, sendo fornecidos o tipo e o texto de referência. A câmera deve ser con�gurada, o que é feito com a de�nição da posição em relação à malha e sua inclinação por meio dos métodos SetRelativeLocation e SetRelativeRotation. Também devemos associar a malha estática e a câmera ao objeto raiz, com base em SetupAttachment. void AMovimento::BeginPlay() { Super::BeginPlay(); } void AMovimento::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (multiplica != 0) { FVector NewLocation = GetActorLocation() + (FVector(0,1,0) * DeltaTime * Velocidade * multiplica); SetActorLocation(NewLocation); multiplica = 0; } } Listagem: Segundo trecho do arquivo Movimento.cpp — Fonte: O autor. Na segunda parte de Movimento.cpp, temos o evento BeginPlay, que pode ser utilizado para inicializações em tempo de execução, e Tick, ocorrendo a cada quadro durante o jogo. Para o nosso exemplo temos a alteração da localização do ator, com base em DeltaTime, Velocidade e sentido da translação (multiplica). void AMovimento::TeclaZ_Mantida() { multiplica = -1; } void AMovimento::TeclaX_Mantida() { multiplica = 1; } Listagem: Terceiro trecho do arquivo Movimento.cpp — Fonte: O autor. No trecho seguinte de Movimento.cpp temos os métodos de resposta ao pressionamento das teclas Z e X, em que o primeiro de�ne a translação para a esquerda, com o valor negativo para o multiplicador, e o segundo para a direita, com o multiplicador positivo. O valor é consumido em Tick, retornando para nulo após mover o objeto. void AMovimento::SetupPlayerInputComponent( UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); InputComponent->BindAction("Tecla_Z", IE_Pressed, this, &AMovimento::TeclaZ_Mantida); InputComponent->BindAction("Tecla_Z", IE_Repeat, this, &AMovimento::TeclaZ_Mantida); InputComponent->BindAction("Tecla_X", IE_Pressed, this, &AMovimento::TeclaX_Mantida); InputComponent->BindAction("Tecla_X", IE_Repeat, this, &AMovimento::TeclaX_Mantida); } Listagem: Quarto e último trecho do arquivo Movimento.cpp – Fonte: O autor. No último trecho do arquivo temos a ligação entre os mapeamentos con�gurados, os eventos e os métodos de resposta internos. As ligações ocorrem utilizando o método BindAction, onde o primeiro parâmetro refere-se ao nome do mapeamento, podendo ser Tecla_Z ou Tecla_X; o segundo de�ne o evento utilizado, aqui sendo adotados IE_Pressed e IE_Repeat, e o terceiro aponta para o método de resposta correto. Evento Utilização IE_Pressed Ocorre no momento inicial do pressionamento de uma tecla. IE_Repeat É repetido durante o período em que a tecla é mantida pressionada. IE_Released Ocorre no momento em que a tecla é liberada. Tabela: Eventos para as ações sobre teclas e outros valores discretos. Fonte: O autor. Não podemos deixar de mencionar as importações necessárias para lidar com a câmera e os objetos criados via programação, bem como o controle dos dispositivos de entrada. #include "Movimento.h" // Controle dos dispositivos de entrada #include "Components/InputComponent.h" // Câmera e componentes de cena #include "Camera/CameraComponent.h" #include "Components/SceneComponent.h" Listagem:Importações utilizadas no arquivo Movimento.cpp – Fonte: O autor. Após compilar o projeto, a partir do editor da Unreal Engine, adicionamos um objeto do tipo AMovimento à cena, posicionamos corretamente, e associamos uma malha estática por meio da hierarquia oferecida no painel Details. Figura: Escolha da malha estática para o objeto Movimento1. Fonte: O autor. Afastando a visualização podemos observar tanto a câmera, criada via programação, quanto a malha estática escolhida, e já estamos em condição de executar o jogo, apertando as teclas Z e X para mover o objeto, com o acompanhamento da câmera, durante a execução. Figura: Instância de AMovimento no ambiente, antes da execução. Fonte: O autor. Embora existam muitas diferenças entre a Unity 3D e a Unreal Engine, certamente o controle de dispositivos de entrada é um ponto de grande relevância. Enquanto a Unreal Engine adota o modelo extremamente robusto, demonstrado aqui, com a necessidade de mapeamentos para todas as entradas adotadas, na Unity 3D temos a possibilidade de veri�car as entradas a partir de um componente centralizador, sem a necessidade de mapeamentos especí�cos. using UnityEngine; public class TestaTeclas : MonoBehaviour { void Update() { if (Input.GetKey(KeyCode.Z)) { Debug.Log("Tecla Z pressionada"); } if (Input.GetKey(KeyCode.X)) { Debug.Log("Tecla X pressionada"); } } } Listagem: Código C# para teste das teclas Z e X na Unity 3D. Fonte: O autor. Atividade 1. A linguagem C++ é extremamente robusta, sendo derivada direta do C, mas com o acréscimo de elementos na sintaxe para dar suporte ao paradigma orientado a objetos. Entre as palavras acrescentadas à sintaxe, qual delas de�ne o ponteiro de autorreferência? a) me b) self c) base d) super e) this 2. Quando criamos um componente para utilização no ambiente da Unreal Engine, devemos derivar a classe de algum dos modelos básicos contidos nas bibliotecas. Para os objetos que podem ser adicionados como elementos da cena, a classe de base mais simples seria: a) Pawn b) Actor c) Character d) PlayerController e) InterpGroup 3. No ambiente da Unreal Engine, as entradas que serão adotadas devem ser mapeadas de forma a permitir o acionamento de métodos das classes, relacionados às entradas utilizadas, podendo ocorrer a partir de eventos especí�cos. Qual o método responsável por efetuar toda a ligação entre mapeamento, evento e método de resposta? a) BeginPlay b) Tick c) SetupAttachment d) BindAction e) SetActorLocation 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. Próxima aula Criação de cenários complexos; Utilização de narrativa em primeira pessoa; Utilização de narrativa em terceira pessoa. Explore mais No site w3schools.com leia sobre Referência da linguagem C++ tradicional, com diversos exemplos. Referência geral da API em C++ para Unreal Engine, disponível no site do fabricante: Unreal Engine. Também em Unreal veja a Documentação do fabricante sobre controle de entradas via Blueprints. javascript:void(0); javascript:void(0); javascript:void(0);
Compartilhar