I move an Actor every frame using AddMovementInput(GetActorForwardVector(), forwardSpeed);
When i move my character forward without deviation he hits a max velocity.X of ~416. His max should be 500.
When I select my character in the details panel while running the game, then click back into the game viewport and move my character forward they hit a max velocity.X of 500.
Y stays 0, Z stays 0. Nothing else changes except I can see my character in the details panel.
When I click another object in the details panel and click back into the viewport then move forward, the velocity.X goes back to the unexpected 416.
I’ve done various tests over the course of a few hours and I believe i have isolated it to the actor velocity only being accurate when the details of the actor in motion is visible. Otherwise the speed is for whatever reason limited.
Am I making an error? Is this expected somehow or a bug? Thank you
Consider to take the delta times into a count and multiply them with your input.
Frame based acceleration without using the delta time leads to different speed with different frames per second. When you do something else your fps change and your speed changes.
Selecting different things in the viewport change your speed. Possibly you also have vsync enabled which caps your input at 60 fps.
But now i’m thinking about maybe AddMovementInput does not expect the speed to be dilated by time. Maybe i need to remove the DeltaTime multiplier in this instance. Appreciate you responding i’ll look at the source code and see if i can reason out what is happening behind the scenes with AddMovementInput, thank you
From what i can see “AddMovementInput()” should take the normalized direction and then a scalarValue that is not tied to framerate. (i.e. scalarValue * DeltaTime seems to be the incorrect approach)
For others running into this problem, here is what AddMovementInput does from what i can tell:
AddMovementInput // multiplies the direction and scalar together and then stores it in the Pawn as “ControlInputVector”
UCharacterMovementComponent::TickComponent // consumes the input vector by calling ConsumeInputVector and stores the Vector in a local variable “InputVector” – seems to potentially toss this update away but generally continues
Retrieves Mesh and ticks it
Handles a networking, seems like prediction and correction code follows, but assuming you have greater authority than SimulatedProxy it continues here and eventually passes InputVector to the following function
void UCharacterMovementComponent::ControlledCharacterMove(const FVector& InputVector, float DeltaSeconds)
{
{
SCOPE_CYCLE_COUNTER(STAT_CharUpdateAcceleration);
// We need to check the jump state before adjusting input acceleration, to minimize latency
// and to make sure acceleration respects our potentially new falling state.
CharacterOwner->CheckJumpInput(DeltaSeconds);
// apply input to acceleration
Acceleration = ScaleInputAcceleration(ConstrainInputAcceleration(InputVector));
AnalogInputModifier = ComputeAnalogInputModifier();
}
if (CharacterOwner->GetLocalRole() == ROLE_Authority)
{
PerformMovement(DeltaSeconds);
}
else if (CharacterOwner->GetLocalRole() == ROLE_AutonomousProxy && IsNetMode(NM_Client))
{
ReplicateMoveToServer(DeltaSeconds, Acceleration);
}
}
It would seem then that AddMovementInput expects a direction and a scalarValue completely separate from DeltaTime and that the good people at Epic handle the frame by frame predicted acceleration behind the scenes.
Also i could easily be very wrong lol but that’s what it looks like