Download

Any way to modify gravity direction for actor?

Hello everyone,
My team and I are very new to the Unreal scene and just recently jumped on the opportunity once we found out that we could integrate many parts of our existing engine into the original UE4 source code. I was wondering if it was at all possible, either with blueprint or using native c++, to change the gravity direction of a specific actor. For example, one object may fall to the wall while another may fall to the ceiling, and the same could apply to characters. Is there an unreal property for this at all, or does this require slightly more code prying to get working?

Cheers,
Joey

Hi joey,

I don’t know about individual actors, but I’ve managed to track down where the gravity is set for the world in the source code.

…\UnrealEngine\Engine\Source\Runtime\Engine\Private\PhysicsEngine\PhysLevel.cpp

Inside



UWorld::SetupPhysicsTickFunctions


line 79



// Update gravity in case it changed
FVector DefaultGravity( 0.f, 0.f, GetGravityZ() );

static const auto CVar_MaxPhysicsDeltaTime = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("p.MaxPhysicsDeltaTime"));
PhysScene->SetUpForFrame(&DefaultGravity, DeltaSeconds, UPhysicsSettings::Get()->MaxPhysicsDeltaTime);


This gets hit every frame to update the world gravity by the locally created vector DefaultGravity. This vector only ever has a value set in the Z axis of which it pulls the effective strength of the gravity from GetGravityZ(). I suggest adding a new function GetGravityVector() and using like so:



FVector DefaultGravity = GetGravityVector();


I’ve just tried negating the value returned by GetGravityZ() in code as a test and it worked for any physics simulated objects. However, the player character (in a sidescroller project) did not fly up to the ceiling. The player is not physically simulated and as far as I know this is common practice in games due to the overhead. I’ll investigate more and find what defines the gravity for the player and hopefully hook it in to a new function that can redefine the gravity for the whole world on the fly.

Hope this helps.

Mike

I’ve made some progress on this, this was actually something I was looking into in UE3 and UDK a few years back but lost interest due to work and the limitations of UnrealScript. I’ve replaced all the hard-coded Z-axis only gravity stuff with a variable vector gravity in the ‘WorldSettings’ and made it exposed to the editor and the blueprint system so it can be set by the designer either at the start of the level or at runtime.

Also started hooking it into the particle system, here’s the progress so far:
https://www.youtube.com/watch?v=O5ACgCpDEzs

Would you be willing to share those changes mwadelin? :slight_smile:

That is so awesome, changing gravity could have a ton of applications. Looks like you managed to keep the effect targeted to a specific area, how did you manage that? Thanks!

Not just yet, there’s still a bunch of stuff that doesn’t work with the gravity changes as nearly all of the math in the engine related to gravity is hard coded into the Z-axis. I’m going through it all in my spare time and updating it, once that’s done I should be able to share it. But in the mean time I’m happy to explain what I’ve changed.

Actually in that video the gravity is global, the 2nd particle emitter is a GPU side one and it’s gravity only gets set upon creation so it doesn’t update on the fly, I think I put that in the video description just to show the difference. I’m looking into getting these working too as GPU emitters allow you to have so many more particles!

However, the localised gravity is definitely something I’m going to add, I think you can kinda do it now with volumes but I don’t know if these are dynamic or not and they definitely don’t work with particles yet.

It’s not the best solution in the world but in case you just quickly want a physics object to have a custom gravity direction what you can do is just turn off the default gravity for that object and then simply apply an impulse per tick at the direction of the gravity that you want * 1040 * object’s mass * delta. -1040 was the default gravity value in UDK and seems it’s the same in UE4.

Long ago with UDK I was concerned that applying an impulse per tick would eventually cause a significant fps drop (assuming you have hundreds of actors using that) but personally I haven’t noticed any performance hit even with many thousand impulses per tick.

Of course that means you will have to set this up for each object you want to have custom gravity and of course it doesn’t effect particles etc. but it’s a quick & dirty solution if you just need a few objects gravitating towards different directions.

@mwadelin
Fair enough. Let us know when you are happy with your changes.

@TK-Master
Thanks for the workaround. I was doing something similar but I was using AddForce rather than AddImpulse. Also i wasn’t multiplying by deltatime or the mass. After I switched to what you suggested it works much better.
One possible correction. I think the default gravity is -980. I searched in the code and found this:
DefaultGravityZ=-980.0

Oh? then they changed it for UE4. 980 makes more sense since it’s closer to earth’s gravity acceleration which is ~9.8 m/s2

Will do, I’m working on it in my spare time so might be a while.

For that work around I would suggest sticking with AddForce; gravity is a force that accumulates velocity over time, an AddImpulse sudden and instant change in velocity at the frame it is applied. I’ve not looked at the code for these functions so I don’t know if they already take into account deltaTime and mass.

And yes the default gravity is -980.0 which is set in the DefaultGame.ini config file. You can edit this to a positive number to have inverted gravity or 0 for no gravity. But you won’t be able to run about on the ceiling and any particle systems will need their emitters to have a specific acceleration set to them to match the gravity set. My changes will (hopefully) integrate this new gravity vector into the player movement controllers and particle systems so that they can be completely dynamic and the player will fall to a surface and still be able to run, walk, etc.

From what I have seen AddForce already accounts for delta (not sure about mass but I’m 99% sure that it doesn’t) however from my testing I have often gotten weird results with it like sudden change of force when fps drops (that happens with AddImpulse too but not as much) which is kinda weird actually since delta time should in theory take care of just that.

As for the velocity accumulation that’s a good point but I still don’t know exactly what the difference between AddImpulse and AddForce is… AddForce is supposed to add some force over time but that doesn’t say that much (what time frame would that even be?) so I stick with impulses since velocity seems to build up just fine, plus the game is updated in steps (every frame) and not continuously if that makes sense, so I don’t think AddForce does anything differently in this case although I would be very interested to find more information about this if someone knows.

An entity will normally have 2 variables that help update it’s position, Velocity & Acceleration. Throughout the frame the user will change these variables and a final new position will be calculated at the end.

The difference is that addForce will normally make a change to the entity’s stored Acceleration whereas addImpulse will make a change to it’s velocity.

They would then normally be used like so:

NewVelocity = Velocity + Acceleration
NewPosition = Position + NewVelocity

This is a simplified example, there would normally be consideration for deltaTime, mass, etc. The reason that example does work is because there are no other forces acting upon it so adding velocity each frame will let it accumulate but this will probably cause problems down the line.

This is the comment from UPrimitiveComponent::AddImpulse source code:

 *	Add an impulse to a single rigid body. Good for one time instant burst.

… and this from UPrimitiveComponent::AddForce:

 *	Add a force to a single rigid body.
 *     This is like a 'thruster'. Good for adding a burst over some (non zero) time. Should be called every frame for the duration of the force.

Also looking at the source code they will both take mass and deltaTime into consideration, you just pass the force you want through, so for regular gravity the force would be 0,0,-980 and that would be passed as the vector every frame for AddForce.

Hope that helps.

Ah I see… If AddForce adds to the object’s acceleration, which should be the rate of velocity (or simply velocity / time) then that makes sense why it already accounts for DeltaTime since time is already integrated to the calculation.
AddImpulse on the other hand definitely does not calculate delta unless you manually multiply the force vector with it (I have tested this, an object will travel way further when the frame rate is higher if you don’t multiply with delta).

So by my understanding, if you multiply the impulse by delta isn’t it essentially the same thing as addforce? :confused: uhh I should probably look into the code sometime it’s kinda confusing :stuck_out_tongue:

Like I say my example above was a simplification, the engine will probably have a lot more things going on behind the scene when you apply a force, especially with regard to the objects mass, centre of gravity and inertia tensor.

You might be getting what appears to be the desired results at the minute due to no other forces acting upon the object but this will probably cause issues when other forces are thrown into the equation.

The only time you should really use an impulse is for a sudden instant change in an object’s velocity, i.e. an explosion, a collision which would see the object deflect off another or another surface, a player pawn jumping (technically you could do this using acceleration over the time it takes the animation of the pawn’s legs pushing up to finish but most games don’t bother).

I’ll try it myself when I get home using AddForce which should work.

I agree with what you say, generally addimpulse should probably be used once (not every frame) for (as you mentioned) explosions, hits and things like that but I’m wondering what the actual difference with addforce would be assuming you apply per-tick for something like gravity simulation, buoyancy, an aircraft thruster and things along those lines… constant forces.

I’ll take a peek later and see :stuck_out_tongue:

I did start looking before but it got buried in class after class so I lost interest.

So sorry about taking this much time to respond. I put the post up, and there wasn’t too much activity within the first few days so I got discouraged.

Anyways, thanks so much for taking the time to answer. Both of those ideas seem quite solid and I’ll start playing around with them. I’ll let you guys know of any performance problems I encounter, or any others for that matter.

Again, thanks so much guys!

If you’re okay with sharing it might I recommend you drop your changes into a fork on Github? This sort of thing would benefit from multiple people working on it, and I think once done you could push it upstream into the main repo if its done properly.

Personally I’m more than happy to share it but I have come to realise that doing so could go against my employment contract. Sorry guys :frowning:

I’m happy to help people out here and share any information about making this work though.

Fair enough mate. Though I’m sure if you had a chat with your employers they would be willing to allow it (I know most are). But if not thanks in advance for making yourself available here too.