For roughly one month, I worked on a gravity project for an independent study in gameplay programming. I created a system to dynamically change the player's gravity direction to land on objects and walk around spheres and capsules.
This ended up being a very technically interesting project, where I got to look into some neat 3D vector math to solve interesting questions to create the gravity system. I also created a couple gravity related mechanics to go with the main gravity tech.
This project's main piece of tech is the gravity system, which uses custom scripts to determine the closest point from the player to a mesh, and directs their gravity vector accordingly. Notably, Unity has a function Collision.ClosestPoint() that does this already, however, this function is really only useful for flat objects with a very low vert count, such as a box.
To solve this problem, I created a variety of scripts that inherit from a gravity object parent class. These scripts go on various objects of different shapes, such as GravityPoint for a sphere, GravityLine for a capsule, GravityPlane for a box, or GravityCircle for the torus shown in the gif to the right!
The player then determines its gravity vector by checking all gravity objects in range, and then picking the closest point with the highest priority to be its gravity point.
GravityPoint and GravityPlane were trivial. Getting the player's closest point to a sphere was simply a matter of drawing a vector to the center of the sphere, and as mentioned previously, Collision.ClosestPoint() can be used to get the closest point to a box collider.
GravityLine is the script used for capsules, which gets the player's closest point to the capsule by drawing a vector pointing towards the closest point on the line in the center of the capsule (Shown in the image to the right).
GravityCircle is the script used for the torus, which I wanted to try because I knew it would be particularly difficult. For awhile, I tried to find a way to graph a circle around the torus and find the closest point to that circle. However, I eventually realized that by drawing a plane through the torus, the player's vector to the center of the torus can be projected onto that plane (Shown in the image to the right). We can then just multiply that vector based on the radius of the torus to get the closest point.
Lastly, I added a couple side-mechanics to pull together the gravity aesthetic. I added a "jetpack" or hover button when holding spacebar in the air, shown by the blue bar. I also added some gravity fields, which have a priority of 0 to guarantee the player is affected by them, and can be changed from upwards to downwards via script or in inspector. Lastly is the 2D areas, which use the gravity field, but also directs the camera to a chosen point and allows the player to switch the gravity direction while inside.