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"