# Simulating circular motion with gravitational forces in Unity2D

I am currently messing around with a game where you control a black hole and use its gravity to fling planets at targets. I have the gravity calculations working pretty well when the planets start out stationary but I want to take it a step further and have the planets start out in circular orbit around the black hole.

Ideally what I want to do is place a planet, provide it with an orbital period, and have it orbit my black hole object in uniform circular motion. To do this I am following these steps:

1. Use the objects initial distance from the black hole ($$\r\$$) and the given orbital period ($$\T\$$) to calculate the standard gravitational parameter of the system ($$\\mu\$$) via the equation $$\\mu = \frac{4\pi^2r^3}{T^2}\$$
2. Find the tangential velocity of the circular motion via the equation $$\v = \sqrt{\frac{\mu}{r}}\$$
3. Assign the object an initial velocity with a magnitude of $$\v\$$ and a direction perpendicular to the vector between the black hole and the object
4. Every time the Update() function is called, apply a force to the object in the direction of the black hole that represents its gravitational pull $$\F=\frac{\mu m}{r^2}\$$ where $$\m\$$ is the mass of the object.

All of these equations came from the Wikipedia page on circular orbit.

When I do all of this I get planets that do orbit the black hole, but their orbits are elliptical and rather unstable while I want them to be perfectly circular. Here is my GravitationalForce script, which I attach to the planet object and provide the black hole object as otherBody.

public class GravitationalForce : MonoBehaviour
{
public GameObject otherBody;

public float orbital_period = 2;

float grav_param;

Rigidbody2D rigidbody2d;
Rigidbody2D rigidbody2d_other;
// Start is called before the first frame update
void Start()
{
// get rigid bodies of this object and the object it is attracted to
rigidbody2d = GetComponent<Rigidbody2D>();
rigidbody2d_other = otherBody.GetComponent<Rigidbody2D>();

// calculate the grav_param for this object
Vector2 position_this = rigidbody2d.position;
Vector2 position_other = rigidbody2d_other.position;

Vector2 dist_vector = position_this - position_other;
float dist = dist_vector.magnitude;

grav_param = (4*Mathf.Pow(Mathf.PI, 2)*Mathf.Pow(dist, 3))/(Mathf.Pow(orbital_period, 2));

// calculate and assign the initial velocity
Vector2 dist_vector_rotated = new Vector2(-dist_vector.y, dist_vector.x);
dist_vector_rotated.Normalize();

Vector2 velocity_vector = dist_vector_rotated * (Mathf.Sqrt(grav_param/dist));

rigidbody2d.velocity = velocity_vector;
}

// Update is called once per frame
void Update()
{
// calculate gravitational force
Vector2 position_this = rigidbody2d.position;
Vector2 position_other = rigidbody2d_other.position;

float dist = Vector2.Distance(position_this, position_other);

float force_magnitude = (grav_param * rigidbody2d.mass)/(Mathf.Pow(dist, 2));

float theta = Mathf.Atan2(position_other.y - position_this.y, position_other.x - position_this.x);

Vector2 force_vector = new Vector2(force_magnitude*Mathf.Cos(theta), force_magnitude*Mathf.Sin(theta));


• Why not use force_vector = - (grav_param * rigidbody2d.mass)/(Mathf.Pow(dist, 3))*(position_this - position_other);? This avoids all the trigonometry and easily generalizes to 3D. – Lutz Lehmann Nov 19 '19 at 11:07
• There's actually a premade script called PointEffector2D which I used a while back, which acts similarly but the orbits (if you can get them into orbit) don't mess up. Also, keep in mind that Update() and FixedUpdate() are separate things. If you're using Unity's physics calculations, you should generally use FixedUpdate(), and RigidBody2D uses Unity's physics calculations. – John Hamilton Nov 21 '19 at 9:27