CPP - Enhanced Input
Ao final deste tutorial, você conseguira criar a configuração de input para controlar um personagem simples em cpp sem utilizar nenhum template.
1. Criando o projeto
Depois de inicializado o launcher de projetos, selecione games e Blank. para iniciar um projeto vazio.
Feito isso vamos criar um novo level vazio. Abra o Content Browser/Drawer clique em uma área vazia com o botão direito, e selecione level.
Feito isso de um duplo clique para abrir seu nível vazio, caso a engine peça salve o novo arquivo.
Neste momento temos apenas uma tela preta, vamos criar as luzes básicas através
do Env. Light Mixer
, para acessa-lo vá em Window > Env. Light Mixer
Nessa janela conseguimos adicionar todas as luzes padrão que a UE espera em um level, basta clicar nos botões que ela fornece: Create Sky Light, Create Atmospheric Light, etc, clique em todos.
Assim, agora teremos um céu azul em nosso cenário.
Vamos criar um chão simples para nosso personagem andar, vou utilizar apenas um brush cilíndrico para isso.
Essa será nossa base de testes, simples, mas efetiva.
2. Enhanced Input
o Enhanced Input é uma nova feature da UE5, que oferece maior flexibilidade para projetos que tem muita alteração do sistema de controle. O que eles chamam de “Dinâmico e Contextual”, ou seja, a depender da interação do seu personagem, é possível fazer o remapeamento dos inputs de maneira rápida, ou ainda ter o mesmo input para ações diferentes dentro do jogo.
2.1 Input Actions
Input Actions definem ações possíveis do seu jogador, e que serão respondidas a
depender dos dispositivos de entrada. Elas podem ser de diversos tipos, bool
que podem ser usados para botões, Axis1D
pode ser o valor de um slider,
Axis2D
pode ser a posição do joystick em um controle, e Axis3D
que pode ser
utilizado para acessar os dados de acelerômetro por exemplo.
Para criar um arquivo de Input Action clique em + Add
no Content
Browser/Drawer, procure por Input e selecione Input Action
Para mater uma organização é bom utilizarmos alguma norma para os nomes de
nossos assets, nos projetos da Epic, ele utilizam muito IA_
como prefixo para
as Input Actions, como falo português, resolver utilizar IAc_
para não
confundir com inteligência artificial.
Salve essa recém criada como IAc_Walk
Com um duplo clique podemos configurar suas propriedades:
2.2 Input Mapping Context
Esse arquivo é um mapa de ações que o jogador pode usar. Para criar um InputMappingContext basta procura-lo abaixo da opção de input action.
Ao abrir esse arquivo podemos utilizar as actions que criamos e mapear para os inputs que queremos.
Em Mappings clique no ícone de +:
Agora podemos selecionar a Input Action que acabamos de criar:
E Clicando no símbolo de + da Action, definir todos os inputs que queremos que acionem essa action:
Temos agora que adicionar alguns modificadores para cada uma das teclas, para fazer o mapeamento correto.
Por padrão, o mapeamento de um botão, seja ele continuo ou discreto, será de 0 a
1 em x. Sem nenhum modificador, todas as teclas responderiam para o mesmo lado,
vamos usar os modificadores Swizzle Input Axis Values
e Negate
Assim nosso mapeamento ficará da seguinte forma:
2.3 Player Controller
Com as Input Actions e o IMC configurado, precisamos de um Player Controller, que irá gerenciar os diversos IMCs de nosso jogo e ativa-lo para o jogador.
Da documentação oficial:
Uma coisa a considerar ao configurar seu PlayerController é qual funcionalidade deve estar no PlayerController e qual deve estar em seu Pawn. É possível manipular todas as entradas no Pawn, especialmente para casos menos complexos. No entanto, se você tiver necessidades mais complexas, como vários jogadores em um cliente de jogo ou a capacidade de alterar personagens dinamicamente em tempo de execução, pode ser melhor manipular a entrada no PlayerController. Nesse caso, o PlayerController decide o que fazer e então emite comandos para o Pawn
Para criar um PlayerControler devemos criar filha desse componente, para isso vá
em Tools > New C++ Class
. Isso irá abrir o “wizard” para escolhermos uma classe base, selecione Player Controller e clique em Next
Selecione o tipo de acesso de sua classe, e dê um nome para ela, e clique em Create Class
Feito isso teremos, como esperado, nossos arquivos header e source:
//LUPC_Default.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "PC_Default.generated.h"
/**
*
*/
UCLASS()
class LEARNINGUNREAL_API APC_Default : public APlayerController
{
GENERATED_BODY()
};
//LUPC_Default.cpp
#include "PC_Default.h"
Precisamos criar uma referência para o Mapping Context que criamos nos passos anteriores, declarar o construtor dessa classe. Mas para isso precisamos declarar em nosso projeto que utilizaremos o Enhanced Input System.
Abra o Arquivo nomeDoProjeto.build.cs
que pode ser encontrado em Source/NomeDoProjeto/
e em PublicDependacyModuleNames
e adicione o modulo que iremos utilizar
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" });
Talvez seja necessário recriar o projeto visual studio.
Feito isso poderemos adicionar os headers necessários:
//LUPC_Default.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "LUPC_Default.generated.h"
/**
*
*/
UCLASS()
class LEARNINGUNREAL_API ALUPC_Default : public APlayerController
{
GENERATED_BODY()
//properties
public:
UInputMappingContext* imc_default;
//methods
public:
ALUPC_Default();
};
E então em nosso source file vamos atribuir a referência para nosso IMC:
Para isso vamos usar o FObjectFinder
do ConstructorHelpers
//LUPC_Default.cpp
#include "UObject/ConstructorHelpers.h"
#include "LUPC_Default.h"
ALUPC_Default::ALUPC_Default()
{
imc_default = ConstructorHelpers::FObjectFinder<UInputMappingContext>(TEXT("objetoaserencontrado")).Object;
}
Depois de criada, vamos fazer o bind do Enhanced Input System com o Player, vá
para o EventGraph da Blueprint e crie o nó Enhanced Input Local Player
Subsystem
Verificamos se ele é valido e caso positivo, adicionamos ao player
Por vezes precisamos desativar a flag de Context Sensitive
para achar o nó que
precisamos
E esse fluxo todo acontecerá no BeginPlay do Player Controller
Não esquece de selecionar seu IMC:
Character
Por fim, vamos criar nosso personagem que iremos controlar, por hora algo extremamente simples!
Crie uma Blueprint Class a partir de Character:
Ao Abrir a blueprint, na viewport você verá que temos alguns componentes padrões do Character:
Vamos adicionar uma malha para visualizarmos nosso player:
E uma câmera, posicione a camera um pouco atras da malha do seu jogador:
Feito isso, vamos para o EventGraph e vamos utilizar o Evento da Action que criamos:
Vamos mapear da forma mais simples possível as entradas do WASD
para
movimentação no mundo, podemos utilizar os valores da Action Value direto,
expandindo o “struct”, clicando com o botão direito do mouse e selecionando
Split Struct pin
Feito isso podemos utilizar a função Add Movement Input:
Game Mode
Caminhando para as ultimas configurações precisamos criar um Game Mode, que é um asset que controla as configurações padrões por level.
Ao Abrir sua blueprint em Classes, selecione o Player Controller que Acabou de criar e o Character Que acabou de criar:
Por fim, devemos definir esse Game Mode nas configurações do nosso nível em World Settings:
Se tudo deu certo você deverá ter um personagem andando pela tela: