AddForce + Timeline interaction frame skipping

Absolute UE beginner here, like 2-3 weeks. All I have is solid coding background in other OOP languages.

Anyhow, I’ve been experimenting with the engine, coming up with various scenario to move things around and have physics applied to them.

I’m not really trying to find a “better way” to do what I’m doing, more so trying to understand why it’s behaving the way it does. Though, if you want to point out other ways to achieve the same result, I’m still all ears as I might learn something new :slight_smile:

I’ve spotted this issue while have a go at various implementation of a Dash ability. Only to realize that with this specific method, he was always moving a teeny tiny more than he should have.

So I reduced the scenario to something quite simple:

  • 1 character with character movement
  • Press F
    • Apply force to the character using Timeline

The problem:

  • Lingering forces that shouldn’t be there. right ?

At least to me, it seems that the last force applied to the character is not applied on the correct frame.
I don’t understand why and it’s driving me :crazy_face:

Here is the EventGraph blueprint (there’s also a bit of C++ to override the character component for logs, nothing fancy)

The FrameCounter is bumped in the event tick, and that’s all the tick does.

Simulating, and only pressing F while doing so (no other keypress), gives me the following output:

I added the >>>>Forces Applied & Cleaned<<<<< bits for clarity, which comes from an overridden UCharacterMovementComponent::ApplyAccumulatedForces that just calls super + log that line (that what is does, at least to my understanding)
But the output is essentially the same without.

As you can see, once the timeline is finished (red cross), there’s no call to ApplyAccumulatedForces before nor after the Finished Timeline log entry.
Completely skipped.
And at the next frame (91) we can clearly see that the force was definitely not applied - as it was in all previous rendered frames.
And I have no clue why :man_shrugging:

Incidentally, I’ve tried to replicate it in other ways without the use of timeline, to try to pinpoint the problem, to no avail, so I’m guessing I must be misunderstanding how Timeline are supposed to work in the UE flow.

So I thought, that or something to do with calling DelayUntilNextTick
But I tested chaining multiple (10 of them) DelayUntilNextTick and AddForce together manually, simulating a timeline effect, but it worked just as expected, so I’m a little clueless as to what is really going on and why the force is not applied there, at the end of frame 90.

I have not yet tested with sidestepping to see what the results could be. Something for latter. I have dug this rabbithole enough for now.

Any help would be appreciated. Feel free to ask any question if any of this wasn’t clear enough.

I think I found out what the issue is. Or more so my misunderstanding about how it’s supposed to behave. Please correct me if I’m wrong but here is the theory:

  • DelayUntilNextTick will trigger once next tick has finished, which is obvious
    However, since we don’t know if the “current tick” has already been done, “current tick” one could very well be the next one (odd to say). Therefore, forces couldn’t possibly be cleaned yet and still need to be applied as haven’t finished ticking.
    My “delay” was being processed within the same tick basically - no clue how to phrase it so it sounds logic :smiley:

In the screenshot, where there’s 2 identical pending forces (at frame 90-91), we are actually still in the same engine tick. So all working as intended I suppose.

In case anyone is interested, I believe I finally got to the gist of it, essentially boils down to the TickGroupOrder

  1. PrePhysics ticks run on my char
  2. Latent Action ticks run my delay node (referenced as n/a in the doc, after PostPhysics)
  3. rinse and repeat next frame

The following simple blueprint highlights the situation:

With all that newfound knowledge, knowing the output should be easy enough, but just in case we have some people who likes a little brain teaser, feel free to try to guess the actual output for frame 1 & 2 for both implementations.

Answer bellow

Answer in the orange blocks.

Notice how first implementation has AB in the first same frame. Doubling down on DelayUntilNextTick on the second implementation only delay the print by actually 1 frame since LatentAction ticks prior rendering the frame.
Long story short, DelayUntilNextTick doesn’t mean your latent action will be processed in the next frame. It means it’ll be processed during the next latent action tick, whatever it may be.

I think I found out what the issue is. Or more so my misunderstanding about how it’s supposed to behave. Please correct me if I’m wrong but here is the theory:

  • DelayUntilNextTick will trigger once next tick has finished, which is obvious
    However, since we don’t know if the “current tick” has already been done, “current tick” one could very well be the next one (odd to say). Therefore, forces couldn’t possibly be cleaned yet and still need to be applied as haven’t finished ticking.
    My “delay” was being processed within the same tick basically - no clue how to phrase it so it sounds logic :smiley:

In the screenshot, where there’s 2 identical pending forces (at frame 90-91), we are actually still in the same engine tick. So all working as intended I suppose.

Pretty much yeah :slight_smile:
It’s obvious now, but when you don’t know better it’s definitely not haha.

I think the hard part for me was understanding that AddForce had no impact on the current frame being drawn, only on subsequent frame the force impact can be seen as the order of ticking was actually as follow:

  1. ApplyAccumulatedForces - CharacterMovementComponent ticking
  2. AddForce - Timeline ticking (these are pending forces)
  3. Physics - pending forces need to wait for next character movement component tick to be taken into account)

Instead of what I initially thought: 2->1->3