The default implementation only supports up/down gravity, as in, gravity can only be applied on the Z-axis.

This is because in UWorld::SetupPhysicsTickFunctions the code reads the world’s gravity value which is only stored as a Z-gravity value. This is then passed into FPhysScene::SetUpForFrame. It doesn’t offer any way of replacing the gravity value directly.

Overriding the default gravity

You can manually call SetUpForFrame in your own tick-logic to replace the engine’s setup with your own. Set your TickGroup to TG_PrePhysics, and put the following code into Tick:

FPhysScene* PhysScene = GetWorld()->GetPhysicsScene();
static const auto CVar_MaxPhysicsDeltaTime = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("p.MaxPhysicsDeltaTime"));
 
FVector Gravity = /* Your custom gravity force here */;
 
PhysScene->SetUpForFrame(&Gravity, DeltaSeconds, UPhysicsSettings::Get()->MinPhysicsDeltaTime, UPhysicsSettings::Get()->MaxPhysicsDeltaTime,
	UPhysicsSettings::Get()->MaxSubstepDeltaTime, UPhysicsSettings::Get()->MaxSubsteps, UPhysicsSettings::Get()->bSubstepping);

This allows you to change the gravity direction so it gets applied into any direction and at any strength you want.

The Big Gotcha

If you change the gravity direction, any sleeping physics bodies won’t be affected. The sleeping body is not affected by gravity until it’s woken up, either by something colliding with it, or code.

You can manually wake up sleeping bodies via PrimitiveComp->WakeAllRigidBodies(). There may be some other way of doing it also that doesn’t require knowing all the primitive components that may be sleeping, but I didn’t find one (yet)

The Smaller Gotcha

It’s quite likely that Character Movement Component will not respect this gravity direction and if you need characters to follow it, you need to deal with that separately.