Add framerate independent force to character

I am so confused. I want to apply forces to my character but not as movement input but more like a dash ability. If i use AddForce of the UCharacterMovementComponent it is not frame independent. I get different results with different frame rates. I also tried AddImpulse but thats also creating different results with different frame rates (even when multiplying with DeltaTime) … im so confused. Im doing nothing more than calling the AddForce with the same Vector.

i have something like this but in c++

The distance the character traveles after pressing M is different depending on the framerate … i tested with 120 and 30 and the difference is like 20% or something like that.

My end goal is to have this working with a timeline so i can have a big force at the beginning and decrease over time but it isnt even working like this with a constant force vector.


Solution: Set the GroundFriction of the CharacterMovementComponent to 0

1 Like

Hello! You can call AddForce with Vector * DeltaTime to deal with different frame rates.

1 Like

yes i tried that … in the description of addForce it says it would be scaled to timeframe but it isnt working either way. I always get a different distance traveled

1 Like

For single-step inputs, you should not multiply by DeltaTime for AddForce, you should divide by DeltaTime.
The reason is that the impulse (acceleration) is defined as force times time.
The force you add will be applied over the given DeltaTime. Thus, if you want a specific impulse to be applied over one time step, you need to divide the magnitude of that impulse by the step deltatime.

However, in the setup you post a screen shot of, you are applying the force over some amount of time.
That amount of time is pretty long – looks like half a second? This is going to be 15 frames at 30 fps, or 30 frames at 60 fps. That should be plenty enough to even out differences in force, somewhat – if your frame rate is not perfectly even, whatever frame goes at the “end” if your input sequence will still get the full force, but will last for some time slightly above the desired 0.5 seconds.

You can improve this behavior by setting the maximum step time to something small, and let physics step more than once during an integration. That still doesn’t quite help with the “half steps” problem – in fact, Unreal just doesn’t have a good solution for that, as it doesn’t yet have a fixed frame rate. (This is a feature they promise for Chaos in UE5, so we’ll see if that shows up!)

Another option is to add this “dash” feature into your simulator itself, and add it as an additional position or velocity boost, rather than a force boost; at that point, you can control the exact shape of how much you add by moving along a curve you design. Record position or velocity when you start, and apply the difference between “current desired boost” and “current actual value” each frame while the boost lasts. You may get more control this way.

Thank you for your answer. I did some testing with AddForce/AddImpulse and DeltaTime and here are my results. I used the BP code From above with a blank third person project. The start position is always the exact same but the distance travels is depentent on the framerate. And it is not acceptable … the difference is huge … to me that dose not seem like is only a issue with the last frame.

(right click and open in new tab for better quality)

The only thing that is working is if i use AddInputVector - then the distance is the same. But i dont want to use that because i dont want to change the movement parameters like max movement speed and so on when executing the dash.

What do you mean with a custom simulator. Do you have a documentation page or something where i can look closer into this?

A first order integrator will never be robust to frame rate differences.
The character movement component does a bunch of work to make the “add input” function be similar across frame rates and networks.
A “custom simulator” means implementing a custom movement mode, which is best read about in the C++ source (this requires C++.)

Honestly, it sounds like temporarily increasing the max movement speed and using add input will be the best option for your use case!

ok thank you

I got the solution … the broblem was not the AddForce or AddImpulse but the character movement configutation. When in Walking mode the GroundFriction gets applied and that is for some reason not framerate independent together with a custom force. So i just set the GroundFriction to 0 for the duration of my dash and everything works fine.

2 Likes

That’s not really a good workaround.

@imtrobin2 feel free to suggest another solution for this issue. At the time i was glad i found this fix for my framerate independance issues. Honestly this could also verry well be a bug … i agree i should not have to set GroundFriction to 0 for framerate independance but this was the only fix i found at the time

I don’t have another solution, sadly but I do plan to use ground friction on surfaces, so this workaround is not great.

can you show how yo do that please. i dont find this option

GroundFriction is a property of the movement component.

I did something like this:

void AMyPlayerCharacter::StartAbilityMotion() {
	if (GetCharacterMovement()->GroundFriction != 0) {
		DefaultGroundFriction = GetCharacterMovement()->GroundFriction;
		GetCharacterMovement()->GroundFriction = 0;
	}
}

void AMyPlayerCharacter::StopAbilityMotion() {
	GetCharacterMovement()->GroundFriction = DefaultGroundFriction;
}