How to make VInterp To FPS independent

Hello, I have a sequence of actors and want they to smoothly follow each other and so I use VInterp To method. The problem is the lower FPS, the lower distance between my actors, but I want the distance alway to be the same.
Around 100 FPS:

15 FPS:

And here is my code:
Event Graph:

Spawn function:

UpdateHeadLocation function:

UpdatePartsLocation function:

Thank you for reading! Any help is really appreciated!

I decided to use VInterpTo() method, after I’ve found this Unreal Engine 3D snake game:

I am using the same VInterpTo() approach like in Snake3D, but in this project the distance between parts is FPS independent,so I don’t understand what I am doing wrong

I don’t necessarily have a direct answer but I do have some observations/questions?

Are the “parts” components attached to the actor (BP_Pawn)? I notice in UpdateHeadLocation that you first move the entire actor, then you follow that up with moving the head by the same amount. Is that not resulting in double the movement? In other words, if you remove that updating of the head part, do you still get proper movement?

A silly efficiency suggestion which I can’t look past (sorry :laughing: )…in UpdatePartsLocation, you are pulling the desired part out of the array in 3 different locations. As good practice, it would be better to simply pull it once to a local variable and use it where needed after that.

Let me noodle on this a bit more. It feels like you’re so close but something is not tied to the frame rate like it should be.

1 Like

Some how, that movement factor you have going on in VInterpTo doesn’t seem right. From a physics perspective, assuming each part is tethered to the other, they should all be moving at the same speed…yet you’re telling each part to reach the other parts location at a different (presumably slower) speed?

…still noodling…it’s an interesting problem

1 Like

Scratch that last comment…I believe you’re using that for the dilation (distance) between your parts so that makes sense.

Alright, I think I’ve convinced myself that you have the implementation correct :slight_smile: .

Something I just noticed though is this from the docs regarding VInterpTo

Interpolate vector from Current to Target. Scaled by distance to Target, so it has a strong start speed and ease out.

It’s that whole “Scaled by distance to Target” piece that concerns me. I would have assumed that VInterpTo was performing linear interpolation but that doesn’t seem to be the case. What’s worse is the fact that the remark above is on the VInterpTo in FMath but not the VInterpTo in UKismetMathLibrary.

FMath::VInterpTo | Unreal Engine Documentation

UKismetMathLibrary::VInterpTo | Unreal Engine Documentation

I’d be willing to bet though that they are the same implementation (if not, one calls the other).

All of this implies that they are not entirely frame rate independent which is the behavior you’re after.

1 Like

Thank you for trying to help me with this problem! Parts are not attached to the actor they are actors, that just follow each other (except head) and so UpdateHeadLocation() doesn’t end up with double movement, because head is a seperated actor.

Hmmm, the fact that they are not completely FPS independent is strange because this project from GItHub also uses VInterpTo() for movement, but the movement doesn’t depend on FPS in it: GitHub - fpwong/Snake3D: 3D snake game made with Unreal Engine 4 for the Ludum Dare 34 Jam
Also I’ve discussed this problem in that Reddit post:
And here some thing I’ve tried to solve the problem:
In UpdateHeadLocation() I tried changing DeltaLocation formula:

  • DeltaLocation = DeltaTime * (Speed / MovementFactor) * ForwardVector.
  • DeltaLocation = Speed / MovementFactor

In UpdatePartsLocation() I tried passing the following expressions to InterpSpeed:

  • Speed / (MovementFactor * DeltaTime)
  • (Speed / MovementFactor) * DeltaTime
  • (Speed * DeltaTime) / (MovementFactor * DeltaTime)
  • Speed * DeltaTime
  • ((Speed * DeltaTime) / (MovementFactor * DeltaTime)) * DeltaTime

Nothing of that worked, unfortunately

1 Like

I here ya, however, if you’re interpolation is non-linear then you’re going to end up with frame rate dependent results. You just might not notice it until you hit extremes like 15 fps. I’m fairly confident that your original setup is correct, we just need to address this non-linear interpolation.

Let’s try this. There is a VInterToConstant node, which appears to be linear interpolation. It should be a drop-in replacement for VInterTo. Give that a shot and see if the results are different.

1 Like

Thank you very much, this worked!
Also sorry for the late response. So I changed VInterpTo() to VInterpToConstant() and now the movement is completely FPS independent.
Around 140 FPS:

15 FPS:

But now there is another big problem, I want my pawn to be able to smoothly move in different directions, but this what happens when I use VInterpToConstant() for this purpose:

And that is the same, but I used VInterpTo() instead of VInterpToConstant() (and of course I increased movement factor):

Also I copied pawn from Snake3D GitHub project and tested it to be shure that the problem is not conneted with project settings somehow and here is the result:
Around 140 FPS:

15 FPS:

And the project author doesn’t use VInterpToConstant():

So I am really confused now.
Any way, gh0stfase1, thank you for your help. I think your solution will definitely help somebody with similar problem. If you want to see my code, I made a GitHub repository of the project:

Again, thank you very much for your help)

Success!..sort of :laughing:

…and agreed, the result with VInterpTo looks much nicer (great node that). If we wanted to replicate that behavior with the constant version then you would want to scale your dilation factor relative to the distance of one piece to another. I would argue that we would then essentially be mimicking what VInterpTo is doing internally and we’ll be in the same predicament.

Ok, so one last crack as I have to know what might be different. I see that you’re putting “GetWorldDeltaSeconds” in for the time delta. While I realize that you would think this should be the same as DeltaTime which comes with event tick, maybe it’s doing something nasty when playing in editor and limiting frame rate. can you try passing the deltatime from event tick into each one of the functions instead?

EDIT: In case it wasn’t clear, I’m saying switch back to VInterpTo and use the DeltaTime from event tick.

1 Like

I tried promoting DeltaSeconds from EventTick to variable and changing all GetWorldDeltaSeconds() function calls on it, but it didn’t work. Moreover I checked if DeltaSeconds equals to GetWorldDeltaSeconds() every tick and the result was always “true”, so this strange behavior is not because of that