How can I get my character to sprint when holding down the LeftShift key?

I know I can easily do this in Blueprint but I am a computer science major and want to do it in C++. I want my character to sprint while LeftShift is down and then return to his default state when LeftShift is released. Currently what is happening is when I press LeftShift he starts sprinting like he should but, once released, never returns to the default state.

void AMyGameCharacter::StartSprint()
{
	CharacterMovement->MaxWalkSpeed = 2000.0f;
	CameraBoom->TargetArmLength = 175.0f;
	CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 0.0f);
}

void AMyGameCharacter::EndSprint()
{
	CharacterMovement->MaxWalkSpeed = 1000.0f;
	CameraBoom->TargetArmLength = 150.0f;
	CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 50.0f);
}

void AMyGameCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
{
	if (FingerIndex == 0)
	{	
		StartSprint();
	}
	if (FingerIndex == 1)
	{
		EndSprint();
	}
}   

Any suggestions on how I can get this working. Thanks heaps in advance!

You are trying to use the the delegate for OnInputTouchBeginto handle both events that you are interested in. Need to use ‘OnInputTouchEnd’ to call ‘EndSprint()’. The ‘ETouchIndex’ is for multi-touch support.

	/** Called when a touch input is received over this actor when and click events are enabled */
	UPROPERTY(BlueprintAssignable, Category="Input|Touch Input")
	FActorOnInputTouchBeginSignature OnInputTouchBegin;
		
	/** Called when a touch input is received over this component when and click events are enabled */
	UPROPERTY(BlueprintAssignable, Category="Input|Touch Input")
	FActorOnInputTouchEndSignature OnInputTouchEnd;

OnInpuTouchBegin and OnInputTocuhEnd are two functions. They will be called when touch started and touch ended respectively (if you have mapped them).

So basically you should call startSprint() inside OnInputTouchBegin and call endSprint() within OnInputTouchEnd.

Like the previous post said, FingerIndex gives you the touch index - applicable only for multi touch screens. It does not indicate if the finger is touched/untouched.

So basically make unreal call two separate functions when touch start and touch end. Then call sprintStart() and sprintEnd() in the respective functions.

PS: I haven’t worked with touch events yet, so I could be wrong.

EDIT:

Sienc you are trying to do everything in C++, you might want to override these 2 AActor functions:
ReceiveActorOnInputTouchBegin
ReceiveActorOnInputTouchEnd

Thanks for the quick reply. I am not familiar with these classes. I don’t think I understand correctly. I added those to Uproperties to my character header file. I am now trying to use them like this

void AMyGameCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
{
	if (OnInputTouchBegin == true)
	{	
		StartSprint();
	}
	if (OnInputTouchEnd == true)
	{
		EndSprint();
	}
}

Which I know isn’t correct since I have syntax errors but I don’t understand how to correctly use them.

Thanks for the insight. I am trying to use it as a function now instead of a variable and I got this going

FActorOnInputTouchBeginSignature AMyGameCharacter::OnInputTouchBegin()
{
	StartSprint();
}

FActorOnInputTouchEndSignature AMyGameCharacter::OnInputTouchEnd()
{
	EndSprint();
}

I am still getting compiling errors so I am still not sure how to use it correctly yet.

I wanted to give an update to what I have. I previous added FActorOnInputTouchBeginSignature OnInputTouchBegin to MyGameCharacter.h file so I removed that since that is already a property of AActors. I override ReceiveActorOnInputTouchBegin and ReceiveActorOnInputTouchEnd as @mindfane pointer out. Here is my current code

MyGameCharacter.h

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#pragma once

#include "GameFramework/SpringArmComponent.h"
#include "MyGameCharacter.generated.h"

UCLASS(config=Game)
class AMyGameCharacter : public ACharacter
{
	GENERATED_UCLASS_BODY()

	/** Camera boom positioning the camera behind the character. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
	TSubobjectPtr<class USpringArmComponent> CameraBoom;

	/** Follow camera. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
	TSubobjectPtr<class UCameraComponent> FollowCamera;

	/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
	float BaseTurnRate;

	/** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
	float BaseLookUpRate;

	/** Player resources. */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
	float Health;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
	float Stamina;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
	float Energy;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
	float Shields;

protected:

	/** Called for forwards/backward input */
	void MoveForward(float Value);

	/** Called for side to side input */
	void MoveRight(float Value);

	/** 
	 * Called via input to turn at a given rate. 
	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
	 */
	void TurnAtRate(float Rate);

	/**
	 * Called via input to turn look up/down at a given rate. 
	 * @param Rate	This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
	 */
	void LookUpAtRate(float Rate);

	/** Handler for when a touch input begins. */

	void StartSprint();

	void EndSprint();

protected:
	// APawn interface
	virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;

	virtual void ReceiveActorOnInputTouchBegin(const ETouchIndex::Type FingerIndex) OVERRIDE;

	virtual void ReceiveActorOnInputTouchEnd(const ETouchIndex::Type FingerIndex) OVERRIDE;
	// End of APawn interface
};

MyGameCharacter.cpp

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

#include "MyGame.h"
#include "MyGameCharacter.h"

//////////////////////////////////////////////////////////////////////////
// AMyGameCharacter

AMyGameCharacter::AMyGameCharacter(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	// Set size for collision capsule
	CapsuleComponent->InitCapsuleSize(42.f, 96.0f);

	// set our turn rates for input
	BaseTurnRate = 45.f;
	BaseLookUpRate = 45.f;

	Health = 1000.0f;
	Stamina = 100.0f;
	Energy = 100.0f;
	Shields = 0.0f;

	// Don't rotate when the controller rotates. Let that just affect the camera.
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;

	// Configure character movement
	CharacterMovement->bOrientRotationToMovement = true; // Character moves in the direction of input...	
	CharacterMovement->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate
	CharacterMovement->JumpZVelocity = 450.0f;
	CharacterMovement->AirControl = 0.1f;

	// Create a camera boom (pulls in towards the player if there is a collision)
	CameraBoom = PCIP.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
	CameraBoom->AttachTo(RootComponent);
	CameraBoom->TargetArmLength = 150.0f; // The camera follows at this distance behind the character	
	CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 50.0f);
	CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller

	// Create a follow camera
	FollowCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FollowCamera"));
	FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
	FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm

	// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
	// are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}

//////////////////////////////////////////////////////////////////////////
// Input

void AMyGameCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
	// Set up gameplay key bindings
	check(InputComponent);
	InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
	InputComponent->BindAction("Sprint", IE_Pressed, this, &AMyGameCharacter::StartSprint);
	InputComponent->BindAction("Stop", IE_Pressed, this, &AMyGameCharacter::EndSprint);

	InputComponent->BindAxis("MoveForward", this, &AMyGameCharacter::MoveForward);
	InputComponent->BindAxis("MoveRight", this, &AMyGameCharacter::MoveRight);

	// We have 2 versions of the rotation bindings to handle different kinds of devices differently
	// "turn" handles devices that provide an absolute delta, such as a mouse.
	// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
	InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
	InputComponent->BindAxis("TurnRate", this, &AMyGameCharacter::TurnAtRate);
	InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
	InputComponent->BindAxis("LookUpRate", this, &AMyGameCharacter::LookUpAtRate);

	// handle touch devices
	InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyGameCharacter::ReceiveActorOnInputTouchBegin);
	InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyGameCharacter::ReceiveActorOnInputTouchEnd);
}

void AMyGameCharacter::StartSprint()
{
	CharacterMovement->MaxWalkSpeed = 2000.0f;
	CameraBoom->TargetArmLength = 175.0f;
	CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 0.0f);
}

void AMyGameCharacter::EndSprint()
{
	CharacterMovement->MaxWalkSpeed = 1000.0f;
	CameraBoom->TargetArmLength = 150.0f;
	CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 50.0f);
}

void AMyGameCharacter::ReceiveActorOnInputTouchBegin(const ETouchIndex::Type FingerIndex)
{
	StartSprint();
}

void AMyGameCharacter::ReceiveActorOnInputTouchEnd(const ETouchIndex::Type FingerIndex)
{
	EndSprint();
}

void AMyGameCharacter::TurnAtRate(float Rate)
{
	// calculate delta for this frame from the rate information
	AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}

void AMyGameCharacter::LookUpAtRate(float Rate)
{
	// calculate delta for this frame from the rate information
	AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}

void AMyGameCharacter::MoveForward(float Value)
{
	if ((Controller != NULL) && (Value != 0.0f))
	{
		// find out which way is forward
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);

		// get forward vector
		const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
		AddMovementInput(Direction, Value);
	}
}

void AMyGameCharacter::MoveRight(float Value)
{
	if ( (Controller != NULL) && (Value != 0.0f) )
	{
		// find out which way is right
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);
	
		// get right vector 
		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
		// add movement in that direction
		AddMovementInput(Direction, Value);
	}
}

I am getting errors on lines 74 and 75

the error reads

Error	1	error C2664: 'FInputTouchBinding &UInputComponent::BindTouch<AMyGameCharacter>(const EInputEvent,UserClass *,void (__cdecl AMyGameCharacter::* )(Param1Type,Param2Type))' : cannot convert argument 3 from 'void (__cdecl AMyGameCharacter::* )(const ETouchIndex::Type)' to 'void (__cdecl AMyGameCharacter::* )(Param1Type,Param2Type)'	C:\Users\jeffd_000\Documents\Unreal Projects\MyGame\Source\MyGame\MyGameCharacter.cpp	74	1	MyGame

InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyGameCharacter::ReceiveActorOnInputTouchBegin);
InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyGameCharacter::ReceiveActorOnInputTouchEnd);

Replace it with:

InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyGameCharacter::processTouchBegin);
InputComponent->BindTouch(EInputEvent::IE_Released, this, &AMyGameCharacter::processTouchEnd);

Undefine the two overrides which I proposed earilier.

Now you need to define two new functions

void AMyGameCharacter::processTouchBegin(ETouchIndex::Type type , FVector loc)
{
   this.StartSprint();
}

void AMyGameCharacter::processTouchEnd(ETouchIndex::Type type , FVector loc)
{
   this.EndSprint();
}

PS: I am abit confused as well.

Are you trying to do a touchscreen game or a PC game?

Because if you are doing it for PC, you dont need this. With this implementation, what happens is your character will sprint when you touch him and he stop sprinting when you release your finger.

To make him run when physical LShift key is pressed. Make an ActionMapping for LShift key in editor. Bind its Pressed and Released events to two functions (StartSprint() and EndSprint() )

However in this case you will use BindAction() instead of BindTouch(). Also the event handler functions’s parameters are different (they take 0 params).

So bascially
InputComponent->BindAction(“Sprint”, IE_Pressed, this, &AMyGameCharacter::StartSprint);

InputComponent->BindAction(“Sprint”, IE_Released, this, &AMyGameCharacter::EndSprint);

This ofcourse assuming that you have defined an ActionMapping called ‘Sprint’ in the editor.

Full code:

Header file:

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#pragma once
 
#include "GameFramework/SpringArmComponent.h"
#include "MyGameCharacter.generated.h"
 
UCLASS(config=Game)
class AMyGameCharacter : public ACharacter
{
    GENERATED_UCLASS_BODY()
 
    /** Camera boom positioning the camera behind the character. */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    TSubobjectPtr<class USpringArmComponent> CameraBoom;
 
    /** Follow camera. */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    TSubobjectPtr<class UCameraComponent> FollowCamera;
 
    /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    float BaseTurnRate;
 
    /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    float BaseLookUpRate;
 
    /** Player resources. */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
    float Health;
 
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
    float Stamina;
 
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
    float Energy;
 
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Pawn)
    float Shields;
 
protected:
 
    /** Called for forwards/backward input */
    void MoveForward(float Value);
 
    /** Called for side to side input */
    void MoveRight(float Value);
 
    /** 
     * Called via input to turn at a given rate. 
     * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
     */
    void TurnAtRate(float Rate);
 
    /**
     * Called via input to turn look up/down at a given rate. 
     * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
     */
    void LookUpAtRate(float Rate);
 
    /** Handler for when a touch input begins. */
 
    void StartSprint();
 
    void EndSprint();
 
	/* TOUCH SPECIFIC */
	void ProcessTouchBegin(ETouchIndex::Type type , FVector loc);
	
	void ProcessTouchEnd(ETouchIndex::Type type , FVector loc);

    /*END OF TOUCH SPECIFIC */


protected:
    // APawn interface
    virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;
 
      // End of APawn interface
};

CPP file

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 
#include "MyGame.h"
#include "MyGameCharacter.h"
 
//////////////////////////////////////////////////////////////////////////
// AMyGameCharacter
 
AMyGameCharacter::AMyGameCharacter(const class FPostConstructInitializeProperties& PCIP)
    : Super(PCIP)
{
    // Set size for collision capsule
    CapsuleComponent->InitCapsuleSize(42.f, 96.0f);
 
    // set our turn rates for input
    BaseTurnRate = 45.f;
    BaseLookUpRate = 45.f;
 
    Health = 1000.0f;
    Stamina = 100.0f;
    Energy = 100.0f;
    Shields = 0.0f;
 
    // Don't rotate when the controller rotates. Let that just affect the camera.
    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;
 
    // Configure character movement
    CharacterMovement->bOrientRotationToMovement = true; // Character moves in the direction of input...   
    CharacterMovement->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate
    CharacterMovement->JumpZVelocity = 450.0f;
    CharacterMovement->AirControl = 0.1f;
 
    // Create a camera boom (pulls in towards the player if there is a collision)
    CameraBoom = PCIP.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
    CameraBoom->AttachTo(RootComponent);
    CameraBoom->TargetArmLength = 150.0f; // The camera follows at this distance behind the character  
    CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 50.0f);
    CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller
 
    // Create a follow camera
    FollowCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FollowCamera"));
    FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
    FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm
 
    // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
    // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
 
//////////////////////////////////////////////////////////////////////////
// Input
 
void AMyGameCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
    // Set up gameplay key bindings
    check(InputComponent);
    InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
    InputComponent->BindAction("Sprint", IE_Pressed, this, &AMyGameCharacter::StartSprint);
    InputComponent->BindAction("Sprint", IE_Released, this, &AMyGameCharacter::EndSprint);
 
    InputComponent->BindAxis("MoveForward", this, &AMyGameCharacter::MoveForward);
    InputComponent->BindAxis("MoveRight", this, &AMyGameCharacter::MoveRight);
 
    // We have 2 versions of the rotation bindings to handle different kinds of devices differently
    // "turn" handles devices that provide an absolute delta, such as a mouse.
    // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
    InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
    InputComponent->BindAxis("TurnRate", this, &AMyGameCharacter::TurnAtRate);
    InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
    InputComponent->BindAxis("LookUpRate", this, &AMyGameCharacter::LookUpAtRate);
 
    /* TOUCH SPECIFIC */
    InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyGameCharacter::ProcessTouchBegin);
    InputComponent->BindTouch(EInputEvent::IE_Released, this, &AMyGameCharacter::ProcessTouchEnd);
   /* END OF TOUCH SPECIFIC */
}
 
void AMyGameCharacter::StartSprint()
{
    CharacterMovement->MaxWalkSpeed = 2000.0f;
    CameraBoom->TargetArmLength = 175.0f;
    CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 0.0f);
}
 
void AMyGameCharacter::EndSprint()
{
    CharacterMovement->MaxWalkSpeed = 1000.0f;
    CameraBoom->TargetArmLength = 150.0f;
    CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 50.0f);
}

/* TOUCH SPECIFIC */
void AMyGameCharacter::ProcessTouchBegin(ETouchIndex::Type type , FVector loc)
{
	this.StartSprint();
}

void AMyGameCharacter::ProcessTouchEnd(ETouchIndex::Type type , FVector loc)
{
	this.EndSprint();
}

/* END OF TOUCH SPECIFIC */
 
void AMyGameCharacter::TurnAtRate(float Rate)
{
    // calculate delta for this frame from the rate information
    AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}
 
void AMyGameCharacter::LookUpAtRate(float Rate)
{
    // calculate delta for this frame from the rate information
    AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}
 
void AMyGameCharacter::MoveForward(float Value)
{
    if ((Controller != NULL) && (Value != 0.0f))
    {
       // find out which way is forward
       const FRotator Rotation = Controller->GetControlRotation();
       const FRotator YawRotation(0, Rotation.Yaw, 0);
 
       // get forward vector
       const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
       AddMovementInput(Direction, Value);
    }
}
 
void AMyGameCharacter::MoveRight(float Value)
{
    if ( (Controller != NULL) && (Value != 0.0f) )
    {
       // find out which way is right
       const FRotator Rotation = Controller->GetControlRotation();
       const FRotator YawRotation(0, Rotation.Yaw, 0);
 
       // get right vector 
       const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
       // add movement in that direction
       AddMovementInput(Direction, Value);
    }
}

I do not have my Dev PC nearby, so I did not test it myself. So expect some compile errors. I am sure you will be able to figure those out.

You can disable the code to handle touch sprinting if not needed. Those functions/headers have comments on top indicating this. Just comment those functions out if you dont want those or they are giving you probblems

In any case go thorugh these two articles for a better understading of Action/Axis/Touch mappings in UE4

https://docs.unrealengine.com/latest/INT/Programming/Gameplay/Framework/Input/index.html

Hey @mindfane thanks so much for your help it works great. I am making a PC game so the whole touch thing was confusing me and it wasn’t necessary since I won’t be developing for Tablets. Anyways it works great thanks a lot!