Download

Accelerate Pawn Movement and Decelerate, using UPawnMovementComponent?

I’m just started to learn Unreal Engine 4.26.2 with C++ and I don’t really know what I’m doing.

I have the following code to move a Pawn (it is a paddle because I’m developing an Atari Pong clone):

void AAIPaddle::MovePaddle(float direction)
{
	float z = GetActorLocation().Z;

	if ((z > -310) && (z < 590))
	{
		float Scale = 100.0f;

		FVector DirectionVector = FVector(0.0f, 0.0f, direction);

		OurMovementComponent->AddInputVector(DirectionVector * Scale);
	}
}

OurMovementComponent is a UPawnMovementComponent.

Ready the description of AddInputVector:

Adds the given vector to the accumulated input in world space. Input vectors are usually between 0 and 1 in magnitude.
They are accumulated during a frame then applied as acceleration during the movement update.

I don’t understand the second sentence… Can I use AddInputVector to accelerate and decelerate the pawn?

I want to accelerate pawn’s movement while the player keep pressed the movement key, and decelerate when the player releases it.

What that sentence says is that, if you call AddInputVector() twice in the same frame, the input vector that the movement component will see when updating the simulation is the sum of those input vectors.

This input vector addition gets cleared when the pawn movement component (subclass) calls ConsumeInputVector()

I don’t think the UPawnMovementComponent actually moves the pawn by itself – I think you’re supposed to override/subclass the component (or add a tick/event handler) that uses the input that’s managed by the component, to actually move the pawn. This is done by the existing subclasses, like Character movement or Floating movement.

Thanks for your answer.

I think a subclass of UPawnMovementComponent moves the Pawn, there isn’t anything else that changes the pawn location. Or I haven’t understood anything.

This is the code that moves the Pawn:

void AAIPaddle::MovePaddle(float direction)
{
	float z = GetActorLocation().Z;

	float Scale = 100.0f;

	FVector DirectionVector = FVector(0.0f, 0.0f, direction);

	OurMovementComponent->AddInputVector(DirectionVector * Scale);
}

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

	if (GameBall->GetVelocity().Y > 0.0f)
	{
		float z = ComputeBallZCoordinate();

		if (z > GetActorLocation().Z)
			MovePaddle(1.0f);
		else if (z < GetActorLocation().Z)
			MovePaddle(-1.0f);
		else
			MovePaddle(0.0f);
	}

}

Yes, you need to do something in either Paddle::Tick(), or create a UPaddleMovementComponent that derives from UPawnMovementComponent and give it a Tick(), where it calls ConsumeInputVector() and then moves the paddle according to the input.

So, you have the AI paddle there – you can create a separate PlayerPaddle that instead of calling ComputeBallZCoordinate() just calls OurMovementComponent->ConsumeInputVector() and uses that to determine which direction to move the paddle (if any.)

Separately, you will want to multiply your movement (MovePaddle()) by the DeltaTime of the tick (and then make the movement value higher, because the unit will be centimeters-per-second.) so that the paddle moves the same no matter what the frame rate.

1 Like

Thanks for your answer.

On UPaddleMovementComponent I have this:

void UPaddlePawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// Make sure that everything is still valid, and that we are allowed to move.
	if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
	{
		return;
	}

	// Get (and then clear) the movement vector that we set in AAIPaddle::Tick
	FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f;
	if (!DesiredMovementThisFrame.IsNearlyZero())
	{
		FHitResult Hit;
		SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);

		// If we bumped into something, try to slide along it
		if (Hit.IsValidBlockingHit())
		{
			SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);
		}
	}
};

On the Player’s Paddle I use this code to move it and I don’t know why:

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

	// Handle movement based on our "MoveZ" axis.
	if (!CurrentVelocity.IsZero())
	{
		const FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);

		if ((NewLocation.Z > -310) && (NewLocation.Z < 590))
			SetActorLocation(NewLocation);
	}

}

Both Paddles use the same UPaddleMovementComponent.

It is hard to find some documentation talking about how to move a Pawn, and it seems that I have tried two different way to do it but know I don’t know what UPaddleMovementComponent does to move the Paddle. I think I must read your answer carefully a lot of times to try to understand them.

Is there any book related to movement that I haven’t read? I ask this because the documentation seems to explain those methods, AddInputVector and ConsumeInputVector, as if I already what it’s talking about.

What does SafeMoveUpdatedComponent do?
Generally, you will want to move the Paddle actor, not just the component.