How I do planet gravitation and orbits


Gravity, it's the reason things fall down. 

I've been fascinated with gravity working on a spherical planet for a long, long time. The culmination is how it is applied in ENCYCLE.

In this game the gravity and jumping mechanic, is working pretty smoothly. And I thought I could share some insights into how that's achieved.


The method that I use for gravity is a combination of stuff that I've tried previously, mainly:

  • Physics based attraction towards objects
  • Cheating by attaching to a Transform parent and inheriting its rotation

A while back I made an FPS adventure game demo called "The Strangehood", where the player walks around on the surface of a spherical planet.


That worked by basically having the player object pivot around the center of the planet, and then on Vertical/Horizontal Axis input, simply rotate around the pivot. Change in terrain height was achieved by shooting a ray straight down and offsetting the player object. The end result was pretty good for a demo.


I have also attempted to achieve walking on a sphere by aligning to surface normal of a downards raycast, and then applying gravity in that direction but the result was too jittery. But aligning to surface normal is a very efficient starting point for achieving this an many other effects.


One of the first approaches I had with the concept that would eventually become ENCYCLE was to have every object exert a gravitational force on the player. That resulted in a pretty simple implementation for each "planet"

  • Find the relative direction between planet and player.
  • Apply gravitational force on the player in direction

This approach works to an extent. But the motion is way to chaotic, and when the player comes into contact with a planet, movement on the surface becomes very hard to achieve. This is because with a physics based controller you now have to apply a forward force and enough downward force as to not shoot off the surface! I am not a physics/math whiz so how to get that balance right eluded me.


So instead I opted for something else. Basically I now do this:

  • From the player object, cast a Ray towards all planets.
  • The ray collides with a "Planet" player which contains .... all planets in the scene.

That means that



And

So that the closest valid object is the one that ends up excerpting gravity.

The function which calculates the current gravity direction runs every 1/2 second approx.

And the gravity is applied in a pretty straight forward manner:

_rigidbody.AddForce(_gravityDir *( gravity * _flyingTime),ForceMode.Acceleration);

I also have the variable _flyingTime which increments while the player is jumping , and has the effect of increasing gravity the longer the player as jumped, this adds a lot to the feel of jumping and landing.

However, this gravity is only applied when the player is airborne.

If the player has impacted a planet things get much simpler. The player is simply made a child of the planet, and its rotation is sped up to match the player speed. Which has the perfect illusion of the player orbiting the planet. 

Jumping is then a simple matter of releasing the player as a child of the planet, and applying a relative force upwards.

And after attempting pretty much every way possible to achieve this kind of gravity the lesson is that there is no universal solution. The key is to identify the stages of your gravity and find ways to approximate the behavior instead of attempting a perfect simulation, I'll leave that to the professional physicists and their supercomputers!

Get ENCYCLE

Leave a comment

Log in with itch.io to leave a comment.