Scaling

“Space is big. You just won’t believe how vastly, hugely, mindbogglingly big it is. I mean, you may think it’s a long way down the road to the chemist’s, but that’s just peanuts to space.”

― Douglas Adams, The Hitchhiker’s Guide to the Galaxy

Scaling a space game is tricky. Spacecraft are game objects that are measured in meters, planets in thousands of kilometers and orbits in millions of kilometers. Unity starts to complain when objects are located beyond 100,000 units from the origin and this imposes a length scale in the rendering of the scene. Additional complications arise in the specification of values for the gravitational physics. We want to be able to map real-world data into values that can be integrated by the physics engine without a loss of precision. To accomplish this all N-body simulations will scale the distances, velocities and masses to attempt to avoid numerical issues.

Given the constraints of Unity position limits and the requirements of numerical precision, it is not possible to use one set of values for position, velocity and time in the Unity scene and the physics engine. In addition it is useful when creating space simulations to be able to provide positions and velocities in “real-world” units (e.g. m, km,AU) and these units may not be suitable for either the scene or physics representations.

As a result we have three “spaces”:

  1. World space (positions designated in real-world units [e.g. AU, km, m] or dimensionless units)

  2. Scene/Display space

  3. Physics space

GE2 tries to make the scaling issues as painless as possible by allowing the designer to specify a typical:

  • orbit size in world units

  • orbit period in game seconds

The GSController component allows the scale parameters to be set via the inspector values:

  • Orbit Scale: size of a typical orbit in the scene in world units

  • Orbit Mass Scale: the mass of the body around which the typical orbit is defined (generally the heaviest object in the scene)

  • Game Sec Per Orbit: the game time desired for one orbit a body at the orbit scale around the orbit mass

GSController uses this information to configure the scaling in the GravityEngine (GE) class it instantiates. The GE API uses world units but internally values are converted into units that are more suitable for numerical integration. The code for this is found in GBUnits.GEScaler.

GravityEngine Internal Units

This section is optional and is provided for those who like to delve into the details.

The N-body simulation in GE models gravity using Newton’s force law and good ‘ol \(F= m a\). These equations describe the inter-related changes in velocity and position of all bodies as a set of differential equations and these are then integrated numerically using one of several standard techniques. It would be a shame not to show these off, so for the record the equations for an N-body gravitational system are:

(1)\[\begin{equation} \ddot{r}_j = \sum_{k=0,k\ne j}^{N-1}\frac{G m_k (r_k-r_j)}{|r_j-r_k|^3}, j=0,...,N-1 \end{equation}\]

where \(r_j\) is the three dimensional position vector of the jth body in Cartesian coordinates, \(m_j\) is the mass of the mth body and G is Newton’s gravitational constant.

Note

Wait, \(r^3\)? The Physics 101 formula for gravity was \(F= G m_1 m_2/r^2\). What’s with the \(r^3\)? The answer is that the equation above is in vector form and the direction of the force is the \(r\) unit vector which is in the direction \((r_k-r_j)\) but is normalized by dividing by its magnitude. This gives us an extra \(|(r_k-r_j)|\) in the denominator in addition to the two from \(r^2=|(r_j-r_k)|^2\).

The goal in the numerical evolution of differential equations is to maintain accuracy by a suitable choice of time step size and ensuring the position and velocity values do not get to large or small. In gravitational N-body systems this is done by re-scaling the system so that:

  • the typical length value for positions is 1.0

  • the typical mass value is 1.0

  • the value of Newton’s constant (normally 6.674E-11 in SI units) is 1 (because who wants to multiple by E-11 everywhere?)

At first this appears to be a lot to ask and it is a bit surprising that all these goals can be achieved. I always need to go back to basics to remind myself so here’s how it works:

The force equation for gravity in one dimension (which is all we need to check the units) is:

(2)\[\begin{equation} m a = G\frac{m M}{r^2} \end{equation}\]

where a is the acceleration, m the mass of one body, M the mass of the other, r the distance between them.

Expressing this in terms of type of units (L=length, T=time, M=mass) and recalling \(a\) has units of \(L/T^2\), rearranging for \(G\) we get:

(3)\[\begin{equation} G = \frac{M L^3}{T^2} \end{equation}\]

This equation has four variables. We can scale three of them as specified above (L=1, M=1, G=1). By doing so we are then constrained to use a time scale which is defined as \(T_{scaled} = T * \sqrt{(G_{si} M_{scale})/L_{scale}^3}\).

For reference, the transform functions for L, V, T and M are provided in the table below. The class GBUnits.GEScaler handles this in GE2.

Scale From

Scale To

Length

Velocity

Time

Mass

world

GE

\(1/L_o\)

\(\sqrt{L_o/(G_u M_o)}\)

\(\sqrt{(G_u M_o)/L_o^3}\)

\(1/M_o\)

GE

world

\(L_o\)

\(\sqrt{(G_u M_o)/L_o}\)

\(\sqrt{L_o^3/(G_u M_o)}\)

\(M_o\)

Note: \(L_o\) is the orbital scale in world units and \(M_o\) is the mass scale. \(G_u\) is the value of Newton’s constant in the selected world units. e.g. \(G_{SI}\)=6.67430E-11 \(m^3/(kg^2 s^2)\).