Applying gravity to a directional vector?

Currently I’m doing something like the below.

if ( Gravity.X != 0.f ) {
	Direction.X = FMath::Clamp( ( Direction.X - ( Gravity.X * DeltaWithTimeDilation ) ), -1.f, 1.f );
}

if ( Gravity.Y != 0.f ) {
	Direction.Y = FMath::Clamp( ( Direction.Y - ( Gravity.Y * DeltaWithTimeDilation ) ), -1.f, 1.f );
}

if ( Gravity.Z != 0.f ) {
	Direction.Z = FMath::Clamp( ( Direction.Z - ( Gravity.Z * DeltaWithTimeDilation ) ), -1.f, 1.f );
}

It’s not quite what I’m after as I need it to be able to loop something around in a circle if enough gravity is applied. Direction is just a normalized vector like after forward vector. Gravity is the same thing. So like X: 0, Y: 0.5, and Z: 0 is just applying a 0.5 gravity onto the directional vector every tick and it works to a degree, but will clamp at -1 or 1 since you can’t go over either for directional vectors.

Anyone have any suggestions here? I’m thinking maybe I can just subtract the gravity straight from the directional vector instead? Maybe something like the below.

Direction = ( Direction - Gravity ).Normalize();

This is for a sphere trace based projectile manager so I have to fake gravity and I want to support gravity against any axis.

I wrote a projectile simulator recently, and I treated gravity just like any other force. So if I was trying to approach your problem, I would simply add the directional vector (multiplied by some value) and gravity (also a vector) together to get the total force. Now you just divide the total force by the mass of your projectile and that’s your acceleration. You apply the acceleration multiplied by delta time to your velocity each frame. And that’s basically physically accurate gravity for you.

What I have at the moment is the following.

float TimeDilation = WorldPtr->GetWorldSettings()->TimeDilation;
float DeltaWithTimeDilation = ( DeltaTime * TimeDilation );
float DeltaSpeed = ( Speed * DeltaWithTimeDilation );

FVector TraceStartLocation = Location;
FVector TraceEndLocation = ( ( Direction * DeltaSpeed ) + Location );
float TraceRadius = ( Radius <= 0.f ? 1.f : Radius );

Location = TraceEndLocation;

if ( ! Gravity.IsZero() ) {
	if ( GravityStart > 0.f ) {
		GravityStart -= DeltaWithTimeDilation;
	}

	if ( GravityStart <= 0.f ) {
		Direction = ( Direction + Gravity ).GetSafeNormal();
	}
}

Location being the location in world space (e.g. actor location). Direction being a normalized directional vector (e.g. actor forward vector). Gravity also being a normalized directional vector. This happens during Tick so the gravity will be applied to the next tick.

This sorta works, but yeah I think I need a different approach. Any suggestions from the above? I basically need to apply a modifier to Direction every frame, but it won’t “rollover” -1 or 1 to allow something to loop in a circle for example if that makes any sense.

I might be having a hard time figuring this out because my terminology is wrong, lol. Maybe it makes more sense to say I need to rotate a normalized vector by another normalized vector?

I think I got it figured out. I’ll leave gravity to apply a change over time locking it to an axis. As for my rotation behavior I can just add a FRotator and rotate the direction vector. Proof of concept in BP worked great so just need to move it to C++. Will provide the final solution here once I’m done, but this lets me applied timed gravity and timed rotations giving me lots of neat options for projectiles.

Settled on the following.

	if ( ! Gravity.IsZero() ) {
		if ( GravityStart > 0.f ) {
			GravityStart -= DeltaWithTimeDilation;
		}

		if ( GravityStart <= 0.f ) {
			Direction = ( Direction - ( Gravity * DeltaWithTimeDilation ) ).GetClampedToSize( -1.f, 1.f );
		}
	}

	if ( ! Rotation.IsZero() ) {
		if ( RotationStart > 0.f ) {
			RotationStart -= DeltaWithTimeDilation;
		}

		if ( RotationStart <= 0.f ) {
			Direction = Rotation.RotateVector( Direction );
		}
	}

Lets me add directional gravity followed by rotation. I can have projectiles that spin, arc, turn around, have “gravity”, etc… working great. Rotation is just an FRotator.