Struggling to create input actor component in c++. Not sure if using the right method?

I currently have input setup on my base character (BaseSkater).

The code is getting lengthy, so I’m trying to move the input setup to it’s own module to keep things tidy and easier to organise moving forwards.

Currently my input component is setup from the BaseSkater source file like so:

void ABaseSkater::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	// Set Up Action Bindings
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ABaseSkater::Move);
	}

I then take the input from the action value to drive my movement:

void ABaseSkater::Move(const FInputActionValue& Value)
{
	//get input values
	const FVector2D MoveValue = Value.Get<FVector2D>();
	LeanInput = MoveValue.Y;
	SteerInput = MoveValue.X;

	//find out which way is forward
	const FRotator ControlRotation = GetControlRotation();
	const FRotator YawRotation(0.f, ControlRotation.Yaw, 0.f);
	const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

	if (bIsRewinding)
	{
		// Rewind logic here
	}
	else
	{
		//movement input
		if (Controller && (LeanInput > 0.f))
		{
			AddMovementInput(Direction, LeanInput);
		}
		//steering input
		if (Controller && (SteerInput != 0.f))
		{
			AddControllerYawInput(SteerInput / SteeringSensitivity);
		}

This all works great and as it should. The problem lies in when i try to move this logic over to a actorcomponent so I can add the input to this, or any other character class that calls the same functions.

Here is how I am trying to do this in my actor component:

SkaterInputComponent.cpp

#include "Input/SkaterInputComponent.h"
#include <EnhancedInputComponent.h>
#include "InputActionValue.h"
#include "EnhancedInputSubsystems.h"
#include <Characters/BaseSkater.h>

USkaterInputComponent::USkaterInputComponent()
{

	PrimaryComponentTick.bCanEverTick = false;

}


// Called when the game starts
void USkaterInputComponent::BeginPlay()
{
	Super::BeginPlay();

}
void USkaterInputComponent::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ABaseSkater::Move);
	}

}

I’m not sure if I’m casting correctly, but it seems to be throwing lots of bugs with the most recent being:

		Severity	Code	Description	Project	File	Line	Suppression State	Details
Error	C2665	'UEnhancedInputComponent::BindAction': no overloaded function could convert all the argument types	DownhillDemonsCPP	E:\DownhillDemonsCPP\Private\Input\SkaterInputComponent.cpp	28		

But from what I understand the argument types are the same? It’s the same code, just in the actor compoonent instead…

I’m hoping somebody can explain where I’m going wrong, or if there is a better way to setup the input as a seperate object that can be attached to the actor to keep code clean?

The last two arguments to BindAction are the object containing the method and the method itself. “this” is your component, not ABaseSkater. Instead of “this”, you need to pass in a pointer to the instance of ABaseSkater actor. In your case, it would likely be the parent or owner.

BindAction has several overloads. The one you’re using is templated, so it’s trying to match the type of “this” with the type of the method and they’re different classes in your code, so compilation fails.

Also, it’s not throwing. That’s a compile error.

Something like this should compile. I’m assuming you’ve move the MoveAction property to the component.

void USkaterInputComponent::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, Cast<ABaseSkater>(this->GetOwner()), &ABaseSkater::Move);
	}
}

edit: A downside of this is that you’ve got coupling to ABaseSkater, so you won’t be able to use this with any actor other than ABaseSkater. There are ways around that, but it’s probably uglier than just leaving all of this in the character’s code.

1 Like

Apologies for the delayed response and thank you so much for the explanation. I think your right, ultimately ABaseskater is the parent class, so it might as well contain the movement code.

Your explanation makes perfect sense.