Last Updated on 13/02/2025
Unreal has Async Physic Tick which helps you to simulate physics with consistent framerate. This is great for replicating physics simulations and for better and accurate physics. Let’s see how you can implement and use Async Tick properly.
Setting it Up
Actor Component & Scene Component
Async Physic Tick is in Actor Component, Scene Component inherints from it so you can use same thing in both.
Found here (ActorComponent.h):

You can do this:
public:
virtual void AsyncPhysicsTickComponent(float DeltaTime, float SimTime) override;
void UMySceneComponent::AsyncPhysicsTickComponent(float DeltaTime, float SimTime)
{
PhysicsTickWorker(DeltaTime); //Function where you keep all your physics tasks
Super::AsyncPhysicsTickComponent(DeltaTime, SimTime); //Add this if you want it to work in Blueprints, this should be at the bottom, after your c++ code
ReceiveAsyncPhysicsTick(DeltaTime, SimTime); //This might get execute in Super, i ran my code without it and it was fine
}
You need to enable Async Tick in constructor, theres this thing but it’s in private:


It goes here:

You can use this function:
I used it in construction and it was fine.

UMySceneComponent::UMySceneComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SetAsyncPhysicsTickEnabled(true);
}
Just don’t put SetAsyncPhysicsTickEnabled in begin play:
It wont trigger in multiplayer, if it doesn’t have owner.

Actor
Almost same thing in Actor:
public:
virtual void AsyncPhysicsTickActor(float DeltaTime, float SimTime) override;
void AMyActor::AsyncPhysicsTickActor(float DeltaTime, float SimTime)
{
PhysicsTickWorker(DeltaTime);
Super::AsyncPhysicsTickActor(DeltaTime, SimTime);
ReceiveAsyncPhysicsTick(DeltaTime, SimTime);
}
Constructor:
AMyActor::AMyActor()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickGroup = TG_PrePhysics;
bAsyncPhysicsTickEnabled = true; //You can access this in here
}
In Actor bAsyncPhysicsTickEnabled is little different:

In actor blueprint it’s this thing:

Enable it in here:

Now we just need to tinker with Async Tick Settings in Edit -> Project Settings.
Enable Tick Physics Async and set the time step.

You can calculate delta time like this (in the box), 1 / 120 which means 120 frames or ticks in second.

AddForce
AddForce applies Delta Time from the main thread so using this in Async tick is the worst thing you can do.
Small physics test that shows why not use AddForce in Async tick. This test was done in 5.5.
This was simple setup, just cube flying straight up. No Gravity.
Final velocity and Travel Distance are the most important. Delta Time was not applied to Add Force, it was applied to Add Impulse.

Also there’s no difference between Add Force At Location or Add Force both will give same result. Accel Change means it just includes mass into force.

AddImpulse
AddImpulse is what you want to use in Async tick. You need to apply Delta Time of async tick into your force calculation before adding it into AddImpulse.
Remember that now you are applying acceleration.
So something like this, will work correctly:

Some of the functions only work in main thread, like get component location or rotation, this can result in stuttering because values are updated in other tick. It’s best to build your own functions which gets the values from the physics rigidbody.
There can be a small stutter on movement which can become visible on high fps (high refresh rate on async tick as well) – you need to use some kind of interpolation plan if you are planning to run async tick on high framerate – type in “smooth” or “framerate” in project settings and you can see some settings related to this problem. You can set Smooth Framerate to activate when fps is in specific range so keep that in mind.
Check out the Mover Plugin, there’s good info about physics & async tick in there:
Syncing Ticks
One important thing you should consider is syncing ticks. Adjusting the application window or changing windowed modes or full screen mode makes the Async tick stall, normal tick includes the time of how long the application was stuck.
Basic example in full screen. No adjusting the app or anything. No server. Async is set to 120 fps.
You can see that in both ticks the bar is filling up the same rate.
All videos are sped up by x4.
Spamming F11 key.
Delta is increasing. Ticks are now off sync.
This is after we implement the fix.
The Fix
First we should count the frames. And then the Delta.

You should think about the time range of counting frames, if application is running 24/7 it can become over 10 million (120 fps x 60 seconds x 60 minutes x 24 hours = 10 368 000 frames). It’s still small in single precision range but you just shouldn’t let it get into millions. So think about resetting the value.
You also need to sync server tick counter to joining clients.
In server & client scenario:
You can simply send rpc command to reset the point counter and delta (you need to reset both same time).

Before:
This is the place where we can apply delta value.

After:
There should be some kind of range where we apply Delta, async tick still needs to run in it’s own rate otherwise it would be just become normal tick.
So if Delta is too large we apply it and set it to zero.

In single player game this really doesn’t matter and it even might be better that way, because it just means that your car, rocket or whatever you are simulating is just taking a pause. But if it’s a race against the clock the clock is moving but the car is not, because clock is using normal tick, so keep that in mind.
Adding the missed frames back to physic object is complicated because you have to sync velocity, angular velocity, location and rotation. So don’t just increase velocity and pray, your car is still in wrong location. If you are using Unreal’s Chaos Vehicle classes it should already have these things brain stormed or not. This is mostly just for building your own simulation classes.
Check out these Unreal Classes for more:
UChaosVehicleMovementComponent | Unreal Engine 5.5 Documentation | Epic Developer Community
UChaosVehicleSimulation | Unreal Engine 5.5 Documentation | Epic Developer Community
UChaosWheeledVehicleMovementComponent | Unreal Engine 5.5 Documentation | Epic Developer Community
UCharacterTrajectoryComponent | Unreal Engine 5.5 Documentation | Epic Developer Community
Classes | Unreal Engine 5.5 Documentation | Epic Developer Community
Coming Up! Rocket Example
Simulating a rocket with async tick and some crazy stuff!