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)
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
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
    • 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"

back

(back to Unreal Engine)