2D Astronomical Simulation

I’m trying to make a game somewhat similar to Universe Sandbox but 2D. Currently I’m just trying to get the gravity simulation to work. My main concern is how to scale everything down to unity’s scale.

My current setup calculates the force between the two objects using irl scale, divide by the planet’s mass to get acceleration, and then scales it down by 1,000,000,000 since I want one unit to be roughly 1,000,000km. I then divide it again by 50 to account for FixedUpdate running 50 times a second, then I mutliply it by 525600 to scale a year down to a minute.

For gravitational force I’m using F = (GM1M2) / Rsqrd
and for orbital velocity v = sqrt( (G*Msun) / R )

``````orbitRadius = Vector3.Distance(sun.transform.position, transform.position);
timeScale = 525600f;
scale = 1000000000f;

directionForce = (sun.transform.position - transform.position);
directionForce.Normalize();

forceValue = (gConst * sunMass.mass * mass) / Mathf.Pow(orbitRadius * scale, 2);

acceleration = forceValue / mass;
acceleration /= scale;
acceleration /= 50;
acceleration *= timeScale;

directionForce *= acceleration;

rb.velocity += new Vector2(directionForce.x, directionForce.y);
``````
``````float initialVelocity = -( (Mathf.Sqrt( ( gConst * sunMass.mass ) / (orbitRadius * scale))) / scale);

rb = GetComponent<Rigidbody2D>();
rb.velocity = new Vector2(0, initialVelocity);
``````

This works more or less but I then try to calculate the orbital velocity and scale it down but the figure I get is around 2000u/s which is way bigger than the gravitational acceleration (roughly 0.004u/s/s) and so the planet shoots off. (I’m also not certain how to apply time scaling on such a large scale since Time.timeScale doesn’t seem applicable but I’m certain my stopgap measure isn’t correct).

I’m sure there’s something simple I’m doing wrong or have forgotten, but I can’t figure it out the past few days. I’m having a lot of fun with the project but this one hiccough keeps coming back to haunt me, any advice and tips would be great, thanks!

You’ll need to use something with much more precision than a `float`, perhaps a `double`

A `float` only has about 6 to maybe as much as 9 digits of precision.

It has a lot of dynamic range, but not precision.

Similarly you’ll almost certainly need to implement some type of floating origin (google it up) as a final step for marshaling data to any GameObjects you use, as those must be driven by Transforms which are all driven off `float`-based datatypes.

“Think of [floating point] as JPEG of numbers.” - orionsyndrome on the Unity3D Forums

Floating (float) point imprecision:

Never test floating point (float) quantities for equality / inequality. Here’s why:

https://starmanta.gitbooks.io/unitytipsredux/content/floating-point.html

Why would you use 2D physics for this? You’re doing all those calculations then asking 2D physics to simply integrate velocity into position. It’s a rigidbody simulation, you don’t need a rigidbody simulation for astronomical simulation, especially because there’s no rigidbody interaction at all. Just use Transforms and Rendering.

`position += velocity * delta-time`
Done!

There are also way, waaaaayy better (than above) numerical integration methods you should be using for your goals.

1 Like