Unreal Engine, C++ Enhanced Input, very small example
From Andreida
Prepare Project
Create Project
- Games / Blank
- C++
- Desktop
- Maximum
- Starter Content: no
- Raytracing: no
- Location: your choice
- Project Name: EI01
- Create
Change Map to Basic
When the UE-Editor is open:
- File / New Level / Basic / Create
- File / Save Current Level as ... / Basic01
- Edit / Project Settings / Maps & Modes / Editor Startup Map: Basic01
- Edit / Project Settings / Maps & Modes / Game Default Map: Basic01
- File / Save All
Create Classes
class MyCharacter
- Tools / New C++ Class
- Parent Class: Character
- Name: MyCharacter
- Create Class
Header File: MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputAction.h"
#include "MyCharacter.generated.h"
UCLASS()
class EI01_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
AMyCharacter();
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void look(const FInputActionValue& iaValue);
void move(const FInputActionValue& iaValue);
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* m_pLookAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* m_pJumpAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* m_pMoveAction;
};
Source File: MyCharacter.cpp
#include "MyCharacter.h"
#include "Components/CapsuleComponent.h"
#include "EnhancedInputComponent.h"
AMyCharacter::AMyCharacter()
{
PrimaryActorTick.bCanEverTick = true;
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
}
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* pPlayerInputComponent)
{
Super::SetupPlayerInputComponent(pPlayerInputComponent);
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(pPlayerInputComponent))
{
EnhancedInputComponent->BindAction(m_pJumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
EnhancedInputComponent->BindAction(m_pJumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
EnhancedInputComponent->BindAction(m_pMoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::move);
EnhancedInputComponent->BindAction(m_pLookAction, ETriggerEvent::Triggered, this, &AMyCharacter::look);
}
}
void
AMyCharacter::look(const FInputActionValue& iaValue)
{
FVector2D LookAxisVector = iaValue.Get<FVector2D>();
if (Controller != nullptr)
{
AddControllerYawInput(LookAxisVector.X);
AddControllerPitchInput(-LookAxisVector.Y);
}
}
void
AMyCharacter::move(const FInputActionValue& iaValue)
{
FVector2D MovementVector = iaValue.Get<FVector2D>();
if (Controller != nullptr)
{
AddMovementInput(GetActorForwardVector(), MovementVector.Y);
AddMovementInput(GetActorRightVector(), MovementVector.X);
}
}
Build
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is.
class MyGameModeBase
- Tools / New C++ Class
- Parent Class: GameModeBase
- Name: MyGameModeBase
- Create Class
Header File: MyGameModeBase.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyGameModeBase.generated.h"
UCLASS()
class EI01_API AMyGameModeBase : public AGameModeBase
{
private:
GENERATED_BODY()
public:
AMyGameModeBase();
};
Source File: MyGameModeBase.cpp
#include "MyGameModeBase.h"
#include "MyCharacter.h"
AMyGameModeBase::AMyGameModeBase()
{
DefaultPawnClass = AMyCharacter::StaticClass();
}
Build
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is, if you did all the previous steps.
class MyPlayerController
- Tools / New C++ Class
- Parent Class: PlayerController
- Name: MyPlayerController
- Create Class
Header File: MyPlayerController.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "InputMappingContext.h"
#include "MyPlayerController.generated.h"
UCLASS()
class EI01_API AMyPlayerController : public APlayerController
{
private:
GENERATED_BODY()
public:
protected:
virtual void BeginPlay() override;
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, Meta = (DisplayName = "Input Mapping Context"))
UInputMappingContext* m_pInputMappingContext;
};
Source File: MyPlayerController.cpp
#include "MyPlayerController.h"
#include "EnhancedInputSubsystems.h"
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
UEnhancedInputLocalPlayerSubsystem* pSubsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
if (pSubsystem && m_pInputMappingContext)
{
pSubsystem->AddMappingContext(m_pInputMappingContext, 0);
}
}
Build
Now build the project. Nothing works so don't even try to test it in the UE-Editor, but the code should compile and link. This is a class that is complete as it is, if you did all the previous steps.
Stuff inside the UE-Editor
Create Actions and Mappings
Actions
- Create folder "Input" in "Content"
- Create folder "Actions" in "Input"
- Inside "Actions" right-click and create
- Input / Input Action / IA_Look
- Input Type: Axis 2D
- Input / Input Action / IA_Move
- Input Type: Axis 2D
- Input / Input Action / IA_Jump
- Value Type: Digital (bool)
- Input / Input Action / IA_Look
Mappings
- Inside "Input" right-click and create
- Input / Input Mapping Context / IMC_Default
- Edit IMC_Default
- Add Mapping
- Select IA_Jump
- Key Value: Space Bar
- Add Mapping
- Select IA_Look
- Key Value: Mouse XY 2D-Axis
- Add Mapping
- Select IA_Move
- Key Value 'W'
- Modifier 1: Swizzle Input Axis Values
- Key Value 'S'
- Modifier 1: Swizzle Input Axis Values
- Modifier 2: Negate
- Key Value 'A'
- Modifier 1: Negate
- Key Value 'D'
- Modifiers: (none)
Create Blueprints
Create a folder "Blueprints" inside "Content", then create these blueprints here.
Character
- right-click MyCharacter and select
- "Create Blueprint class based on MyCharacter
- Name: BP_MyCharacter
- Path: Content/Blueprints
- Edit the blueprint (should automatically be opened after creation)
- Input
- M P Look Action: IA_Look
- M P Jump Action: IA_Jump
- M P Move Action: IA_Move
- Compile, save and close the blueprint
- Input
PlayerController
- right-click MyPlayerController and select
- "Create Blueprint class based on MyPlayerController
- Name: BP_MyPlayerController
- Path: Content/Blueprints
- Edit the blueprint (should automatically be opened after creation)
- If you don't see "Input Mapping Context" inside "Input", then
- close the blueprint
- Save All
- close the UE-Editor
- Start the UE-Editor
- Edit the blueprint
- Look for Input / Input Mapping Context
- Set it to your IMC_Default
- Look for Input / Input Mapping Context
- Compile, save and close the blueprint
GameMode
- right-click MyGameModeBase and select
- "Create Blueprint class based on MyGameModeBase
- Name: BP_MyGameMode
- Path: Content/Blueprints
- Edit the blueprint (should automatically be opened after creation)
- Player Controller Class: BP_MyPlayerController
- Default PawnClass: BP_MyCharacter
- Compile, save and close the blueprint
Set your GameMode as the used one
- (Window / ) WorldSettings / Game Mode / GameMode Override: BP_MyGameMode
Test it all
- File / Save all
- Play the level
- Left click into the world
- use the mouse to move your view around
- use w/a/s/d to move
- jump with "space"