How can I move Character class via PlayerController?

Hello.
I’m very new to UE4 C++ programming and stuck at implementing character control bindings with PlayerController class.
For learning, and realizing loose coupling, I want to implement control bindings in Controller Class.
(I’m supposing API connection like: Controller ⇔ Character Control Interface class, or Character Base class ⇔ individual Character classes. through this pattern, I think I can avoid implementing control bindings in each Character class. if this design pattern/concept is weird in UE4 C++ programming/game development, please tell me common pattern),
How can I do that?
Here’s my code.
FPSSandBoxControllerBase.cpp is a main section of this topic.


FPSsandBoxControllerBase.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include <Runtime/Engine/Classes/Camera/CameraComponent.h>
#include "FPSsandBoxControllerBase.generated.h"

/**
 * 
 */

UCLASS()
class FPSSANDBOX_API AFPSsandBoxControllerBase : public APlayerController
{
	GENERATED_BODY()

public:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
		APawn* ControlledPawn;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
		float BaseTurnRate = 25.0f;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
		float BaseLookUpRate = 25.0f;

public:
	AFPSsandBoxControllerBase();

	virtual void OnPossess(APawn* InPawn) override;

	virtual void SetupInputComponent() override;
	virtual void AddPitchInput(float) override;
	virtual void AddYawInput(float) override;

	void MoveForward(float);
	void MoveRight(float);
	void Attack();
	
};

FPSsandBoxControllerBase.cpp

#include "FPSsandBoxControllerBase.h"

AFPSsandBoxControllerBase::AFPSsandBoxControllerBase()
{
}

void AFPSsandBoxControllerBase::OnPossess(APawn* InPawn)
{
	ControlledPawn = InPawn;
}

void AFPSsandBoxControllerBase::SetupInputComponent()
{
	Super::SetupInputComponent();

	InputComponent->BindAxis("MoveForward", this, &AFPSsandBoxControllerBase::MoveForward);
	InputComponent->BindAxis("MoveRight", this, &AFPSsandBoxControllerBase::MoveRight);
	InputComponent->BindAction("Attack", IE_Pressed, this, &AFPSsandBoxControllerBase::Attack);
	InputComponent->BindAxis("LookUp", this, &AFPSsandBoxControllerBase::AddPitchInput);
	InputComponent->BindAxis("Turn", this, &AFPSsandBoxControllerBase::AddYawInput);
	//InputComponent->BindAxis("TurnRate", this, &AFPSCodeReadingCharacter::TurnAtRate);
	//InputComponent->BindAxis("LookUpRate", this, &AFPSCodeReadingCharacter::LookUpAtRate);
}

void AFPSsandBoxControllerBase::MoveForward(float Value)
{
	if (ControlledPawn != NULL && Value != 0.0f)
	{
            // with this code, character does not move forward
		ControlledPawn->AddMovementInput(PlayerCameraManager->GetActorForwardVector(), Value);
            // code below not worked either
		//auto Rotation = GetControlRotation();
		//const auto Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
		//ControlledPawn->AddMovementInput(Direction, Value);
	}
}

void AFPSsandBoxControllerBase::MoveRight(float Value)
{
	if (ControlledPawn != NULL && Value != 0.0f)
	{
		//ControlledPawn->AddMovementInput(PlayerCameraManager->GetActorRightVector(), Value);
	}
}

void AFPSsandBoxControllerBase::Attack()
{
}

void AFPSsandBoxControllerBase::AddPitchInput(float Value)
{
	APlayerController::AddPitchInput(Value);
}

void AFPSsandBoxControllerBase::AddYawInput(float Value)
{
	APlayerController::AddYawInput(Value);
}

FPSsandBoxCharacterBase.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "FPSSandBoxCharacterBase.generated.h"

UCLASS()
class FPSSANDBOX_API AFPSSandBoxCharacterBase : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AFPSSandBoxCharacterBase();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};

FPSSandBoxCharacterBase.cpp

#include "FPSSandBoxCharacterBase.h"

// Sets default values
AFPSSandBoxCharacterBase::AFPSSandBoxCharacterBase()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	//PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AFPSSandBoxCharacterBase::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AFPSSandBoxCharacterBase::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}
1 Like