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 CharacterMovementComponent will not respect this gravity direction and if you need characters to follow it, you need to deal with that separately.