Dynamic gravity for characters


OLD first post follows: [HR][/HR]

Ninja Character code plugin 0.9.3 for Unreal Engine 4.21.1+ is up! Go to and grab the ZIP file (not the green button) from one of the mediafire links posted at the top part (if error 404: log in to Github, link your UE4 account to Github**, links are always online).

This is for C+±based game projects.


VERY OLD first post follows: [HR][/HR]

NinjaCharacter subclass is up! Go to >> << and grab the ZIP file (not the green button) from the link posted at the top part (if error 404: log in to Github, link your UE4 account to Github).
I see no harm if I share the code I have now, let me know what you think if you use this.
This is for vanilla Unreal Engine 4.12.2 and 4.13.1, you still need Visual Studio to compile your game project; detailed instructions are provided.


VERY VERY OLD first post follows: [HR][/HR]

This is a showcase of my code adaption of the standard CharacterMovementComponent from Epic Games. Once they’re ready (UPDATE: they’re ready >, changes will be shared with everyone through GitHub ( (if error 404: log in to Github, link your UE4 account to Github), which might be merged into UE4 by Epic (UPDATE: progress aborted). Code changes are based on an updated 4.7 version of the engine. [HR][/HR]
I need help; the last function I modified is UCharacterMovementComponent::PhysicsRotation(), where you can read this:

if( DesiredRotation.Yaw != CurrentRotation.Yaw )
    NewRotation.Yaw = FMath::FixedTurn(CurrentRotation.Yaw, DesiredRotation.Yaw, DeltaRot.Yaw);

if( DesiredRotation.Pitch != CurrentRotation.Pitch )
    NewRotation.Pitch = FMath::FixedTurn(CurrentRotation.Pitch, DesiredRotation.Pitch, DeltaRot.Pitch);

if( DesiredRotation.Roll != CurrentRotation.Roll )
    NewRotation.Roll = FMath::FixedTurn(CurrentRotation.Roll, DesiredRotation.Roll, DeltaRot.Roll);

It calculates the interpolation between the current rotator and the desired rotator by using each component of RotationRate (DeltaRot = RotationRate * DeltaTime). This is incompatible with arbitrary capsule orientations, the DeltaRot.Yaw should only affect the local horizontal orientation of the capsule.

How would you fix this problem? Any idea? I already had some and attempted to implement them, but they weren’t correct.

Wow that is looking great!!!

As for your code question: I guess it depends on the frame of reference for the DesiredRotation and CurrentRotation. If they are transformed to local space, then shouldn’t it work as-is, and then you transform back to world space?

Another approach may be Quaternion Slerp. I might need more context in terms of what space you are working in.

Very cool project, Xaklse! We would love to see this reviewed and integrated at some point.

I’m curious how you decided to manage the various gravitational influencers. We had talked about this here in the past and thought that having functions like UWorld::GetGravityAt( const FVector& Location ) and a UWorld::GetUpVectorAt( const FVector& Location ) might be a good approach. Those functions would be optimized for a single fixed gravitational influence, but could also be implemented to support all sorts of influencers.


This is fantastic!! I need this in my life :slight_smile:

'Looks really cool ! :o
I’m afraid I can’t help regarding your coding questions, but I’m looking forward for a testable version.

DesiredRotation and CurrentRotation are determined in world space; I need the FRotator that transforms CurrentRotation into DesiredRotation, avoiding “gimbal lock”, then interpolate a fraction, but knowing, for example, that the max allowed “Pitch angle” is determined by the CurrentRotation local space, and that RotationRate is an Euler FRotator. Haaa, it’s complex… do you get it? Or is it more simple than I thought?

I tried to interpolate current XYZ axes with desired XYZ axes, but what’s pitch, yaw and roll in this case? Did some experiments with azimuth and elevation (FMath::GetAzimuthAndElevation()).

About quaternion slerp, I do use it, but only if all components of RotationRate are equal. See:

		if (DeltaRot.Roll == DeltaRot.Yaw && DeltaRot.Yaw == DeltaRot.Pitch)
			// Calculate the spherical interpolation between the two rotators.
			const FQuat CurrentQuat(CurrentRotation);
			const FQuat DesiredQuat(DesiredRotation);

			// Get shortest angle between quaternions.
			const float Angle = FMath::Acos(FMath::Abs(CurrentQuat | DesiredQuat)) * 2.0f;

			// Calculate percent of interpolation.
			const float Alpha = FMath::Min(FMath::DegreesToRadians(DeltaRot.Yaw) / Angle, 1.0f);

			NewRotation = (Alpha == 1.0f) ? DesiredRotation : FQuat::Slerp(CurrentQuat, DesiredQuat, Alpha).Rotator();


That sounds great Mike; I don’t really manage gravity by zones yet, I just used last known reverse floor normal for the video when gravity is in DYNAMIC mode.
I’ll probably leave this matter to you, since that change should affect classes that I prefer to not modify without proper experience.

As a non-coder but lover of Prey and the weird fun that playing with gravity brings, thank you very much!

Great work! Im looking to mess with gravity my self and you have givin me a great starting poin

Do you achieve the dynamic orientation and dynamic gravity by the normal of the surface or do you have volumes that tell the character how to act when in different location?

I just used the last known reverse floor normal; Epic has some nice ideas regarding zone-based gravity (check Mike’s comment above).

So to achieve this do you rotate the character and apply the gravity in the negative up vector of the character?

Also do you call this when the character is in physics mode or not grounded? or do you Tick the rotation function?

I have been trying to read through the code on how Uworld, the character, and the character component all work. I want to implement the gravity change so that it effects other physics actors and vehicles. Is there any information directly related to how gravity actually works through all of the classes.

Would love to have a full picture of how gravity affects everything in UE4!

This is exactly what I need to develop a game concept I have! So awesome! However, I don’t want to wait for 4.8. Can I just replace the CharacterMovementComponent files in the engine to get this working myself or would I need to do other things?

Cool! Love the music :wink:

  1. Capsule is rotated by floor normal; walking character moves along floor while surface is ‘walkable’, you could walk without gravity, I think it’s similar to Unreal’s old spider physics mode.
  2. I don’t get the question. Stuff is done per-tick, that’s how Epic programmed character movement.
  3. I don’t think there is any documentation, I guess mainly because gravity is always fixed to (0,0,-1). Look for other threads in these forums, you might find something useful for you.

I didn’t upload the source code yet.

Do you know when you will upload the code? Whatever you do, I think you are doing an amazing job!

Very cool stuff! I’m working on something similar as well currently and I’m looking forward to seeing your solution. I’ve got dynamic gravity working pretty quickly, had no time to figure out the orientation yet.

I wonder if there’s a smart way to utilize the Distance Field to determine the gravitational gradient based on arbitrary gravitational influencers…

No, I don’t know. Sooner than later, because I think I’m almost done.

Would love to see a full PR with this feature, having custom gravity will let us do really crazy stuff!

Rather, what you could do is get the hit position of the floor right before the action (jumping, falling, being launched in the air…), then make a plane out of that position and the normal direction of the plane, and calculate the distance from the player to that plane. There you can generate the gravity gradient easily.

If your concern is more about gravity gradient to the OBJECT, you might want to do something more customized, like have an actor posing as the center of mass / gravitational center of your object, then raytrace from your player actor to the gravity point actor and calculate that line’s collision with the object, and the length of that vector would e distance from the floor, in which gravity gradient can be handled that way :V

something more customizable could be a bunch of volumes, or combining volumes with the aforementioned point-line method.

The code is up!
The base code branch is official ‘promoted’ changelist 2484152 (19/Mar/2015) which is newer than version 4.7.3.