Custom Pawn Velocity Always Zero

I’m messing around with pawn movement, so I followed the wiki and added a UPawnMovementComponent to a custom Pawn class. It moves around the level nicely, but every time I attempt to get it’s direction or velocity the result is always zero.

E.g.:

Calling the pawn’s GetVelocity() and taking the length of the vector returns zero.
Even if I set a variable on the class in c++ and grab it via blueprints, it’s zero.

So the pawns movement code looks like:

void AMyPawn::MoveForward(float AxisValue)
{
	FVector CameraVector = m_Camera->GetForwardVector();
	CameraVector.Z = 0.0f;
	CameraVector.Normalize();
	m_Direction = CameraVector;
	if (GetMovementComponent() && (GetMovementComponent()->UpdatedComponent == RootComponent))
	{
		GetMovementComponent()->AddInputVector(CameraVector * AxisValue);
	}
}

This works great, it moves around nicely, but GetVelocity always returns zero and I cannot figure out why. It’s moving the RootComponent (which is a capsule), is it because the pawn isn’t moving, but the capsule is?

Here is the constructor of the Pawn:

AMyPawn::AMyPawn()
{
	PrimaryActorTick.bCanEverTick = true;

	m_CapsuleComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("RootComponent"));
	RootComponent = m_CapsuleComponent;
	m_CapsuleComponent->SetCapsuleHalfHeight(100.0f);
	m_CapsuleComponent->SetCapsuleRadius(40.0f);
	m_CapsuleComponent->SetCollisionProfileName(TEXT("Pawn"));

	m_CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
	m_CameraSpringArm->SetupAttachment(RootComponent);
	m_CameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));
	m_CameraSpringArm->TargetArmLength = 300.0f;
	m_CameraSpringArm->bEnableCameraLag = true;
	m_CameraSpringArm->CameraLagSpeed = 3.0f;

	m_Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));
	m_Camera->SetupAttachment(m_CameraSpringArm, USpringArmComponent::SocketName);

	//Setup our mesh
	m_Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
	m_Mesh->SetupAttachment(RootComponent);
	static ConstructorHelpers::FObjectFinder<USkeletalMesh> MeshAsset(TEXT("/Game/Characters/Test.test"));
	if (MeshAsset.Succeeded())
	{
		m_Mesh->SetSkeletalMesh(MeshAsset.Object);
		m_Mesh->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
	}

	m_MovementComponent = CreateDefaultSubobject<UPlayerPawnMovementComponent>(TEXT("PlayerMovementComponent"));
	m_MovementComponent->UpdatedComponent = RootComponent;

	AutoPossessPlayer = EAutoReceiveInput::Player0;
}

Here is the movement class, for reference:

void UPlayerPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	// Make sure we can move
	if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
		return;

	FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * RunSpeed;
	if (!DesiredMovementThisFrame.IsNearlyZero())
	{
		FHitResult Hit;
		SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);
		if (Hit.IsValidBlockingHit())
		{
			SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);
		}
	}
}

Just to clarify, the issue is, when you want to find out the speed of the pawn, for animations or the like, it never returns a correct speed, so in blueprints when you do Pawn → GetVelocity() → Get Vector Length() it’s zero. So I think I messed up somewhere but where I don’t know.

This is because the movement components are required to set the velocity by themselves. If you take a look into FloatingPawnMovement::TickComponent, it first applies the input vector to the velocity, calculates the delta out of the velocity, moves the pawn, and then re-adjusts the velocity in case of collision. And don’t forget to call UpdateComponentVelocity() whenever you have changed the velocity!

This is how APawn returns the velocity

FVector APawn::GetVelocity() const
{
	if(GetRootComponent() && GetRootComponent()->IsSimulatingPhysics())
	{
		return GetRootComponent()->GetComponentVelocity();
	}

	const UPawnMovementComponent* MovementComponent = GetMovementComponent();
	return MovementComponent ? MovementComponent->Velocity : FVector::ZeroVector;
}

It checks if the root component is simulating physics, if it is, it returns the component velocity.
If it doesn’t, it checks for the MovementComponent and returns the MovementComponents velocity.

So I guess that your MovementComponent isn’t setting the Velocity variable.

This was it, I didn’t do my homework on velocity calculations and should have used a different base class, probably Character.

Thank you, this makes sense, my movement class has nothing to calculate velocity built into it.