Last active
February 21, 2023 10:26
-
-
Save oliverholmberg/de738361a07246991b56 to your computer and use it in GitHub Desktop.
Orbital Gravity 2D - A demonstration of Orbital Gravity in a 2D Unity Game. Unity's standard physics engine implements gravity only in the vertical axis. Here's a demo of orbital gravity for space type games. It allows for one object (spaceship, satellite, etc.) to achieve a stable organic orbit around another object (planet, moon, star, etc.)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
using System.Collections; | |
// Intended to be attached to a GameObject in order for that object to have its own gravity. | |
// Standard Unity Gravity is disabled on objects implementing this class | |
// This class is pared down from the original WorldBodyController used Oliver Holmberg's game Apogee to simply demonstrate orbital gravity. | |
public class OrbitalGravityObject : MonoBehaviour { | |
// Physics settings | |
// The relative mass of the object | |
public float mass; | |
// The radius of the "sphere of influence" This can be set to infinity (or a very large number) for more realistic gravity. | |
public int soiRadius; | |
// Used to alter (unatuarally) the coorelation between the proximity of the objects to the severity of the attraction. Tweak to make orbits easier to achieve or more intersting. | |
public int proximityModifier = 195; | |
// On init of obj | |
void Start() { | |
mass = mass * 100000; // Mass ^ 5 in order to allow the relative mass input to be more readable | |
} | |
// Creates a visual representation of the sphere of influence in the editor | |
public void OnDrawGizmos() { | |
// Show the Object's Sphere Of Influence | |
Gizmos.DrawWireSphere (transform.position, soiRadius); | |
} | |
void FixedUpdate () { // Runs continuously during gameplay | |
// Get all objects that will be affected by gravity (Game objects are tagged in order to be influenced by gravity) | |
GameObject[] objectsAffectedByGravity;objectsAffectedByGravity = GameObject.FindGameObjectsWithTag ("affectedByPlanetGravity"); | |
foreach (GameObject gravBody in objectsAffectedByGravity) { // Iterate through objects affected by gravity | |
Rigidbody2D gravRigidBody = gravBody.GetComponent<Rigidbody2D> (); // Get the object's Rigid Body Component | |
float orbitalDistance = Vector3.Distance (transform.position, gravRigidBody.transform.position); // Get the object's distance from the World Body | |
if (orbitalDistance < soiRadius) { // If the object is in the sphere of influence (close enough to be affected by the gravity of this object) | |
// Get info about the object in the sphere of influence | |
Vector3 objectOffset = transform.position - gravRigidBody.transform.position; // Get the object's 2d offset relative to this World Body | |
objectOffset.z = 0; | |
Vector3 objectTrajectory = gravRigidBody.velocity; // Get object's trajectory vector | |
float angle = Vector3.Angle (objectOffset, objectTrajectory); // Calculate object's angle of attack ( Not used here, but potentially insteresting to have ) | |
float magsqr = objectOffset.sqrMagnitude; // Square Magnitude of the object's offset | |
if ( magsqr > 0.0001f ) { // If object's force is significant | |
// Apply gravitational force to the object | |
Vector3 gravityVector = ( mass * objectOffset.normalized / magsqr ) * gravRigidBody.mass; | |
gravRigidBody.AddForce ( gravityVector * ( orbitalDistance/proximityModifier) ); | |
} | |
} | |
} | |
} | |
} |
Good work!
I would move the code inside in the FixedUpdate into a physics trigger collider. Doing FindGameObjectsWithTag every FixedUpdate is very performance intensive.
Depending upon 2D or 3D aspect of the game, OnTriggerEnter or OnTrigger2D you can check the tag of the object being triggered. That way you can also just use the trigger size as checking the distance!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey, great work - I just found two little typos when trying it out:
line 13
public int soiRadius
should be:
public int soiRadius;
line 53
massToUse
should be:
mass
thx!