Hello Epic Team,
First of all I’d like to thank you guys for the incredible work done with this engine!
Issue:
When Possessing a character with a PController, any movement the AIController was doing before the possess event is immediately stopped. Storing and re-applying velocity/movement input on possess doesn’t prevent the character from pausing for a frame or more.
Question:
Do you guys plan on implementing a Blueprint Accessible option to choose whether or not the character movement should stop immediately when there’s a restart? Usually called on PController Possess Event as well as Character Possess.
More Details:
My main issue being that I can’t make a custom version of Restart functions called by the PController on the Pawn (OnPossess event in PController) because the SetupInput functions from the Pawn are not accessible on the PController.
The Character Restart() can easily be overwrote since it inherits from Pawn.
I’ve been spending a few days on this issue and it seems the best way to handle is to make a custom build from source just for the one line of code in APawn::Restart() that calls Stop Movement Immediately on Character restart (character spawn, possess event by PController, possess event on character).
I have C++ classes in my project but making an entire custom engine build for this one line of code that is buried under multiple inheritances seems a bit overkill.
So I was wondering if it’s planned to add a bool or some other variable easily accessible to modify this behavior?
Solution without altering engine source files
Overriding APawn Functions from MyCharacter and calling these new functions instead of APawn function from MyPlayerController OnPossess event.
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "MyCharacter.generated.h"
UCLASS()
class RUGBYPROJECT_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMyCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
virtual void Restart() override;
virtual void PawnClientRestart() override;
void DispatchRestart(bool bCallClientRestart);
};
MyCharacter.CPP
#include "MyCharacter.h"
#include "GameFramework/InputSettings.h"
#include "Engine/InputDelegateBinding.h"
#include "MyPlayerController.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Character.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
// 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 AMyCharacter::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
void AMyCharacter::Restart()
{
// ACharacter Function
JumpCurrentCount = 0;
JumpCurrentCountPreJump = 0;
bPressedJump = false;
ResetJumpState();
UnCrouch(true);
UCharacterMovementComponent* MyCharacterMovement = GetCharacterMovement();
if (MyCharacterMovement)
{
MyCharacterMovement->SetDefaultMovementMode();
}
// A PAWN FUNCTION
ConsumeMovementInputVector();
RecalculateBaseEyeHeight();
}
void AMyCharacter::PawnClientRestart()
{
UCharacterMovementComponent* MyCharacterMovement = GetCharacterMovement();
// ACharacter Function
if (MyCharacterMovement != nullptr)
{
// CharacterMovement->StopMovementImmediately();
MyCharacterMovement->ResetPredictionData_Client();
}
// APAWN FUNCTION
Restart();
AMyPlayerController* PC = Cast<AMyPlayerController>(Controller);
if (PC && PC->IsLocalController())
{
// Handle camera possession
if (PC->bAutoManageActiveCameraTarget)
{
PC->AutoManageActiveCameraTarget(this);
}
// Set up player input component, if there isn't one already.
if (InputComponent == nullptr)
{
InputComponent = CreatePlayerInputComponent();
if (InputComponent)
{
SetupPlayerInputComponent(InputComponent);
InputComponent->RegisterComponent();
if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
{
InputComponent->bBlockInput = bBlockInput;
UInputDelegateBinding::BindInputDelegatesWithSubojects(this, InputComponent);
}
}
}
}
}
void AMyCharacter::DispatchRestart(bool bCallClientRestart)
{
if (bCallClientRestart)
{
// This calls Restart()
PawnClientRestart();
}
else
{
Restart();
}
NotifyRestarted();
}