Gravity Engine Doc (1.4)

Doc for Version 1.4 (updated Feb 27th, 2017)

New in 1.4:

  • customize gravity to any force you wish
  • OrbitData calculates time to closest approach
  • minor bug fixes

Code Documentation: http://nbodyphysics.com/gravityengine/html/

Overview

Gravity Engine (GE) provides a powerful, accurate physics engine to simulate gravity including:

  • Double-precision simulation of masses and particles using force calculations and optional (per-body) use of two-body Kepler evolution
  • Creation of orbits with control of shape, inclination and orientation.
  • Solar system model for ANY planet, comet or asteroid
  • Gravitational collisions with particle ejection effects
  • Simple spaceship example that allows accurate movement under gravity with projected trajectory
  • A library of over 50 three body solutions with special purpose algorithms to allow simulation through near-misses
  • Centralized control of simulation units (km, AU, arbitrary), overall evolution speed, distance and mass scales

It is not necessary to understand the details of the gravitational physics. Gravity can be added to a scene without scripting.

Code Documentation: http://nbodyphysics.com/gravityengine/html/

Support: nbodyphysics@gmail.com

Tutorials

Overview

Units – Earth Orbit

Build the Solar System

Binary Stars

Orbits

Collisions

Particles

Orbit Prediction

Tutorials are also available from the Title bar in a drop down from Gravity Engine 1.3 and the NBodyPhysics YouTube channel: https://www.youtube.com/channel/UCxH9ldb8ULCO_B7_hZwIPvw

Package Overview

Fundamental Classes

There are three key classes involved in adding gravitational evolution of objects to your Unity project:

  1. GravityEngine – the script that performs all the physics calculations and updates object positions in the scene.
  2. NBody – a script attached to all bodies to be controlled by the GravityEngine. Used to specify their mass and initial velocity.
  3. GravityParticles – added to a particle system to allow it to be evolved by the GravityEngine

The GravityEngine is a very flexible physics engine that provides:

  • Choice of dimensionless or real-world units for distance, mass and time
  • Ability to scale chosen units to achieve the desired game “feel”
  • Advance options to select:
    • Physics algorithm
    • Time steps per frame for algorithms
    • Performance optimizations for gravitational particles
    • Options to allow objects to be detected automatically or added via scripts

NBody Orbit Scripts

Finding the exact initial velocity that creates a specific orbit can be challenging, requiring either physics calculations or trial and error. To eliminate the need for this there are a number of scripts that can be used in addition to the NBody script to control the initial conditions of a body to create a specific orbit.

These scripts will show the path of the orbit in the scene view as the objects are added.

OrbitEllipseTeser.png

There are several options for adding initial conditions or constraining the motion of an NBody object:

  • OrbitEllipse – start a body in a specified elliptical orbit around another body. The body can be moved using gravitational force, or it can move in a fixed path using Kepler’s Equation.
  • OrbitHyperbola – set the velocity to achieve a specfic hyperbolic orbit
  • Binary Pair – initialize a pair of NBody objects so that they form a binary pair with specified orbits. Based on interactions with other bodies the actual orbit followed may change.
  • FixedObject – object does not move, however it’s mass will influence other objects in the scene

Gravitational Particles

GravityEngine allows particle systems to move based on the gravitational field. Particles are treated as massless bodies and are subject to the gravity of NBody objects in the scene. An existing particle system can be placed under the control of the GravityEngine by adding a GravityParticles script.

DustRingTeaser.png

The GravityParticles script can also have an optional delegate that controls the initialization of the particles. Several delegates are provided:

  • DustBall – a spherical shell of particles moving at a specified initial velocity
  • DustBox – a 3D rectangle of dust with individual control over size in (X,Y,Z)
  • DustRing – a ring of particles that orbit around a massive NBody parent. The orbit parameters can be controlled. Useful for effects like planetary rings.

Collisions

Collisions between NBody objects are detected using Unity colliders. Since these collisions are due to gravitational interactions, the NBodyCollision class handles updates to the physics. The collision can be handled in one of three ways:

  1. Absorb
  2. Bounce
  3. Explode
  4. Explode or Bounce (based on contact velocity)

In each case the physics engine is updated as required and momentum and energy are conserved.

Documentation

Gravitational Objects

GravityEngine

Scripting

GravityEngine is the primary class in the asset. For gravitational motion the scene must contain an object with a GravityEngine component. This can be added via the Unity Menus (GameObject/3D Object) or by adding the GravityEngine script to an existing object in a scene.

GravityEngine evolves objects that have an NBody script attached. NBody defines the mass and initial velocity. The GravityEngine can automatically detect all NBody objects in a scene when it starts (the default), be given an explicit list of objects, or objects can be added by script calls to GravityEngine.AddBody().

The engine operates on the FixedUpdate() cycle to ensure that physics evolution tracks game time. In some cases the exact amount of evolution in a specific cycle will vary slightly depending on whether the evolution algorithm has run ahead or behind on previous cycles.

In general the GravityEngine attributes cannot be changed while the scene is running (with the exception of the timescale attribute).

The inspector view shows the key parameters:

GEInspector1v4

SCALING

Units

Gravity Engine allows a choice of units in the game positions. In gravity force calculations it is convenient/efficient to set the force constant G=1.

The follow unit choices are supported:

  1. DIMENSIONLESS: Arbitrary units used directly in the force calculations. When selected the inpector allows Mass Scale and Time Scale to be varied.
  2. SI: Units are in m/kg/sec. See Real-Unit scaling below.
  3. ORBITAL: Units are km/1E24 kg/hours. See Real-Unit scaling below.
  4. SOLAR: Units are AU/1E24 kg/years. See Real-Unit scaling below.

Mass Scale

The GravityEngine allows for the changing of mass scale of all NBody objects in the scene with a single parameter. Initial velocities of NBody objects will also be scaled such that paths taken by the bodies will not change when mass scale is altered.

Adjusting mass scale can be a useful way to change the speed at which things happen in the scene. As the mass scale increases, forces between the bodies increase and the evolution in the scene happens faster. This is the most common technique for adjusting the overall speed of the evolution in the scene.

Mass scale adjustments do not affect the amount of CPU time used in gravitational evolution.

To delve further, see the section Scaling below.

TimeScale

The timescale controls the ratio of time in “the physics world” as compared to time in the game. It can be used to control the overall speed but this happens in a way that affects the CPU time used for gravitational evolution. A timescale value larger than 1 performs more calculations per cycle. A timescale value of less than one will result in fewer calculations per cycle. In either case the evolution calculations will have the same accuracy.

Real-Unit Scaling

When using non-DIMENSIONLESS units the inspector allows a choice of Unity units per distance unit (e.g. Unity units per km). Changing this scale will automatically adjust the distances between all objects in the scene.

Time scale is also adjustable for non-DIMENSIONLESS units (e.g. game sec. per hour). This change, combined with the length scale and use of G=1 in the force equation results in the internal calculation of a mass scale that ensures the correct evolution in the scene.

ADVANCED

Algorithm

There are a number of possible algorithms for gravitational evolution. They vary in accuracy and computational complexity.

  1. Leapfrog: The best default choice. This is a computationally cheap algorithm with a fixed time step that conserves energy well.
  2. Hermite: A variable time-step algorithm that will spend more CPU cycles when objects get close to improve accuracy.
  3. AZTTriple: A special case algorithm for ONLY three bodies. It is a “regularizing integrator” that allows objects to get infinitely close without numerical instability. Typically used in conjunction with the ThreeBodySolution class.

Force

The force chooser allows control over the force law used in the engine. The default choice is standard gravity (Newton’s force law). Other choices are described in the force modification section.

Optimize Massless Bodies

NBody objects with a mass of zero (massless) are influenced by other bodies’ mass but do not affect others. The GravityEngine detects this and massless bodies are evolved separately using a Leapfrog algorithm. This reduces the CPU cost of evolving massless bodies since the interactions between them are skipped.

If there is a need to use the Hermite algorithm for massless bodies then this toggle can be cleared and no massless optimization will occur.

Automatically Add Nbodies

When selected the GravityEngine will examine all objects in the scene (during the Awake phase) and take control of the evolution of those bodies that have an NBody or GravityParticles component.

In cases where this behavior is not desired (e.g. a player spaceship is not moved while the rest of a solar system is) this option can be unselected. In this case the inspector will show a new section to list the bodies that should initially controlled. Existing scene objects with an NBody component can be dragged onto the Bodies list.

In both cases additional bodies can be added via calling GravityEngine.AddBody() and particles systems via GravityEngine.RegisterParticles()

Evolve At Start

By default the GravityEngine will begin evolving all the NBody/GravityParticles objects in the scene when the system starts. Clearing this checkbox can disable this. When cleared, evolution will start when GravityEngine.SetEvolve (true) is called.

Physics to World Scale

A scale factor used to adjust the distance scale used in the physics engine to the Unity positions in the scene. Physics positions are determined by dividing their Unity positions by this factor.

For example, if two bodies are 10 units apart and the physics to world scale is 1 the GravityEngine will use 10 as the distance between bodies. In some initial conditions from the scientific literature the distance scale defined in may be in a very small range, typically (-1..1). It is easier to use these values in the physics calculations because it avoids the need to scale masses and velocities. In this case, setting the physics to world scale to 10 and then positioning the bodies 10 units apart will result in them being scaled down by 10 in the physics calculations and the physics algorithm will see them as 1 unit apart.

This parameter is used by the the ThreeBodySolution code to allow three body physics that is specified in the range of [-1,1] to be displayed using a larger scale in a Unity scene.

Physics Steps Per Frame

This parameter defines the approximate number of times per frame the physics engine will re-calculate positions for NBody objects. A larger number will result in more accurate physics at the cost of more CPU effort. Default value is 8.

Physics (Particles) Steps Per Frame

This parameter defines the approximate number of times per frame the physics engine will re-calculate positions for particles. A larger number will result in more accurate physics at the cost of more CPU effort. Default value is 2.

Nbody

The GravityEngine evolves objects with an NBody script attached to them.

The inspector view for a general NBody object depends on the choice of units. For DIMENSIONLESS units it is:

nbody-dimensionless

For a scene with real-world units it is:

nbody-units

Mass

Mass is specified in dimensionless units. A value of less than zero will be set to zero.

Initial Pos

In those cases the object position is set by the transform component in the usual manner. When real-world units are used the position in real-world units is specified here and the objects position in the scene is calculated based on the length scale specified in the GravityEngine component.

This field is not used in dimensionless units.

Velocity

A Vector3D specifying the initial velocity of the Nbody. If the initial conditions are controlled by an additional component (e.g OrbitEllipse) this field may not appear. The inspector view for an object that has another component providing initial conditions for motions (i.e. an OrbitEllipse or BinaryPair component) will look like:

NbodyEllipseFInal.png

In this case the initial velocity is determined by another component.

Automatic Particle Capture Size/Particle Capture Radius

If automatic capture size is selected, the particle capture size will be taken from the scale of a child object containing a MeshFilter object. This corresponds to typical use of NBody objects in which a child is a 3D Sphere. This ensures the particle capture size matches the sphere.

Any particle that enters the capture radius of an NBody will be inactivated.

If the automatic checkbox is cleared, a value for capture radius is required.

OrbitEllipse

An Orbit around another object can be initialized with the OrbitEllipse component. This script must be attached to a game object containing a NBody component. Typically, the object around which this NBody object is to orbit is the parent. For example:

StarWithChild.png

Selecting an OrbitEllipse object or the parent object will show the ellipse in the scene view.For a brief summary of orbit parameters see Lakdawalla’s Blog. Adjusting these parameters and seeing the result is the best way to gain insight into their role.  In cases where the inclination is zero, Ω and will do the same thing.

The inspector view of this component is:

OrbitEllipse.png

Evolve Mode

There are two modes in which OrbitEllipse operates:

GRAVITY_ENGINE mode will initialize the velocity of the NBody to launch it on the specified orbit. Forces from other bodies may affect the NBody and affect its path. Changes made to the body via GravityEngine.ApplyImpule() will change the path the object takes. This is the mode that is used when correct physics is important.

KEPLERS_EQN mode will force the planet to follow the specified orbital path. The mass of the NBody will affect other bodies but they will not affect it. This mode is used when deterministic motion is required (at the cost of physical accuracy). It can also be useful in large orbital systems – since Kepler’s equation uses less CPU than calculating all the forces between bodies in a large orbital system.

Center Object

Displays the name of the object around which this body will orbit. This is detected automatically if the object is the child of another NBody object. It can also be set explicitly to any object in the scene with an NBody component.

Parameter Choice

Selects whether the size is specified as semi-major axis (a) or distance of closest approach (p).

Pericenter/Semi-Major Axis/Eccentricity/Ω/i/

  1. Size: specified by either the semi-major axis (a) or the point of closest approach, the periapse (p).
  2. Shape: Controlled by eccentricity in the range 0 to 1. A circle has e=0, an infinitely thin ellipse has e=1. GravityEngine will limit e to a maximum of 0.99
  3. Orientation: Celestial mechanics uses a specific choice of Euler angles defined as follows:
    1. Ω (longitude of the ascending node)
    2. Angle of inclination
    3. (angle from ascending node to pericenter)

Experimenting with orientation parameters in the scene view and observing the changes in the ellipse is the best way to understand these parameters. (The ascending node is the point where the object moves through the reference (x,y) plane in the +Z direction. The “line of nodes” is the line where the ellipse crosses the reference plane, assuming the inclination is non-zero. See the Wikipedia page on Orbital Elements.)

Starting Phase

Defines the objects initial position on the ellipse in degress (0..360).

OrbitHyper

Initializes a hyperbola path around a central object. This script must be attached to a game object with an NBody component. When selected the path of the orbit will appear in the scene view.

OrbitHyper-Pic.png

Hyperbolic orbits by definition have an eccentricity > 1.

OrbitHyper-Inspector.png

Pericenter/Semi-Major Axis/Eccentricity/Ω/i/

The same as OrbitEllipse, with the requirement that eccentricity be greater that 1.

Initial Distance

Sets the initial distance from the center object where the orbit evolution will being. By default this will be on the inbound portion of the hyperbola.

Initial Distance Outbound

When set, indicates that the initial distance should be used to position the body on the outbound leg of the hyperbola.

OrbitRenderer

OrbitRenderer.png

The OrbitRenderer component works in conjunction with a LineRenderer to show the predicted orbit path in the scene view during game play. The script must be attached to an object with an OrbitEllipse or OrbitHyper component – from which the orbit path will be determined at the time the scene starts.

A body may not exactly follow this path if there are interactions with other masses. The OrbitRenderer is attached to a game object that is a child of the NBody to allow for separate material selection.

To see the orbit, the Line Renderer component must be correctly configured (i.e. add a suitable material)

A prefab “OrbitPath” is provided.

OrbitPredictor

The OrbitPredictor script predicts the orbital path a body will take given the current velocity of the body and draws the path using a LineRenderer. The projected orbital path updates on each FixedUpdate() cycle – so the influence of user provided velocity changes or changes due to interactions with masses other than the central body will be reflected in the updated path.

Orbit prediction is done using a two-body calculation, transforming the position and velocity with respect to the center body into orbital parameters. The predicted orbit will be accurate if the center body is the dominant source of gravity. If there are other significant sources of gravity in the scene the prediction will not be accurate. [Solving the general orbit prediction problem is not mathematically possible in most cases and would require a simulation of the future evolution of the system – which is impractical].

Screen Shot 2016-08-23 at 6.33.33 AM.png

CenterBody: The NBody containing object around which the orbit should be calculated.

Body: The body for which the orbit will be calculated.

Number of Points: The number of points to use in the line renderer to represent the orbit.

Adding an OrbitPredictor component will automatically add a LineRenderer component. To see the orbit, the Line Renderer component must be correctly configured (i.e. add a suitable material)

Screen Shot 2016-08-23 at 6.35.55 AM.png

The orbit predictor script adds an OrbitEllipse and a OrbitHyper component to the object on which it resides. It instantiates a helper class OrbitData that determines the orbit parameters based on the velocity of the object and the center object. The eccentricity resulting from this calculation is used to activate the elliptical or hyperbolic orbit display as appropriate. In the case of elliptical orbits the OrbitData class also determines the time to closest approach (the variable tau).

OrbitSimpleDecay

This script provides a simple per-frame reduction in velocity and results in the decay of an object in orbit.

Binary Pair

Binary star systems are very common. Configuring a pair of objects in a specific orbit around the center of mass can require careful calculation of the initial velocities. The BinaryPair component handles this task and provides a scene view of the resulting orbits.

BinaryPair-Scene.png

The BinaryPair component is added to a top-level game object and two “stars” are added as children. These stars each have an NBody component that describes their mass. By selecting the BinaryPair object in the scene view the orbits of the objects will be displayed and can be adjusted. GravityEngine provides a binary pair as a prefab object.

BinaryPair-Inspector.png

Velocity

Specifies the velocity of the center of mass of BinaryPair.

Ellipse Parameters

See the description of fields in OrbitEllipse above.

FixedObject

Adding a FixedObject component to an NBody game object creates an NBody object that has a mass but remains at a fixed position.

Gravitational Particles

Gravity Particles

Adding a GravityParticles component to a Unity particle system will allow the GravityEngine to move the particles according to the gravity of all objects in the scene. The particles will be treated as massless bodies and evolved using a Leapfrog algorithm.

Particle creation can be done by the Unity particle system component or can be over-ridden by adding a component that implements the IGravityParticlesInit interface (scripts DustBall, DustBox and DustRing demonstrate how this is used).

The particle system must operate in World Space. This particle system attribute will be changed automatically (and a Warning issued) if it is set to local.

Scenes with large numbers of GravityParticles can require more from the CPU. Care must be taken when adding large numbers of particles to ensure game performance is still acceptable. Reducing the steps per frame for Particles in the GravityEngine may also be useful.

GravityParticles.png

Initial Velocity

The initial velocity to be added to all particles from the particle system on creation. This option only appears if there is no init script attached to the component.

Dust Ball

DustBall implements IGravityParticlesInit and is used to initialize a sphere of particles all moving at the same velocity.

DustBall.png

Velocity

Initial velocity of the particles in the dust ball.

Radius

Radius of the dust ball.

Dust Ring

This script initializes a ring of particles around an NBody object.

The shape and orientation of the ring are controlled in the same way as an OrbitEllipse object.

DustRing.png

Ellipse Parameters

See the description under OrbitEllipse, above.

Width

Defines the width of the particle ring as a percentage of the radius.

Dust Box

Initializes particles in a 3D box.

DustBox.png

X_size/Y_size/Z_size

Size of the X, Y and Z axes of the box. Box will be centered at the transform position.

Velocity

Initial velocity of dust particles

Rotation

3D rotation of the dust box. (Rotation must be controlled here and not in the game object transform to ensure correct rendering by the GravityEngine).

ExplosionFromNBody

ExplosionFromNBody creates a cone of particles that ‘explode’ away from an NBody object. It determines the required velocity to escape the gravitational field of the NBody such the particles reach a specified distance from the body.

ExplosionFinal.png

Explosion Size/Velocity Adjust

The maximum distance the explosion particles should travel before falling back to the NBody on which the explosion is occurring.

The size is used to determine the initial velocity of the explosion. In cases where there is a large initial velocity due to a massive NBody or small radius, the first integration step may move the particles too far. This will result in the size being exceeded. The Velocity Adjust field can be used to “tune down” the initial velocity. Typically values in the range of 0.7-0.9 are useful.

Cone Width

Defines the width of the ejection cone in degrees (from center axis to outside).

Velocity Spread

The variation in the velocity applied to the particles. The value used in the standard deviation around the velocity required to obtain the indicated size. A value of 0 will ensure all particles start at the same speed, larger values will give a wider range of velocities resulting in a more spread out value.

This component is usually triggered by a collision between NBody objects.

Collisions

GravityEngine relies on the Unity collider components to detect collisions via trigger events. It does not make use of them to handle the physics of the collisions.

NBodyCollision

NBodyCollision is attached to the CHILD of an NBody object. It is typically attached to a MeshFilter object with a Collider and Rigid Body attached. The Collider/Rigid body configuration must be:

  1. Collider IsTrigger Enabled
  2. Rigid Body IsKinematic Enabled
  3. Rigid Body Mass set to 0 (will appear as a very small number in inspector)
  4. RigidBody UseGravity Disabled

The NBodyCollision object will handle the trigger events from the collider and interact with the GravityEngine to achieve the desired outcome.

NBodyCollision.png

Collision Type

Defines how the collision should be handled. One of:

ABSORB_IMMEDIATE: On trigger detection the object and its NBody parent will be removed from the scene. The parent NBody’s momentum will be added to the body that it made contact with.

ABSORB_ENVELOP: Once the body with this component has completely entered the other body (based on sphere sizes) the object and NBody parent will be removed from the scene. The parent NBody’s momentum will be added to the body that it made contact with. Envelop works reliably only when the sizes of the objects are different.

EXPLODE: On contact the object and NBody parent will be removed and a particle explosion will be triggered. When selected this element requires an additional parameter: Explosion Prefab

BOUNCE: On contact the parent NBody will reverse direction (as will the parent NBody of the object it made contact with). When selected a Bounce Parameter is displayed. This is value in the range 0..1 with 1 indicating a no energy loss full bounce.

EXPLODE_OR_BOUNCE: Based on contact velocity either explode or bounce.

Collision Precedence

In cases where two bodies with NBodyCollision scripts collide, one must take precedence. The body with the lower precedence will be run. If the precedences of the objects are equal, the Unity game object unique id is used to break the tie.

System Builders

Solar System

screen-shot-2016-10-27-at-5-32-08-am

Scenes with planets, comets and asteroids can be created using the SolarSystem component. A prefab of this object is provided in the Prefabs/SolarSystem folder.

The Solar System component is interactive and provides an “Add Body” button to start a dialog to allow the developer to select the object type (Planet/Asteroid/Comet) and the specific object. If the object is not in the database provided there is an option to open the Jet Propulsion Lab/NASA database in a browser so the desired object can be found. The orbital parameters for the object can then be pasted into the object creation dialog. The JPL/NASA database lists all known comets and asteroids – over 500,000 objects in total!

When using the Solar System builder the unit system in the Gravity Engine must be set to SOLAR. This selects units of AU, 1E24kg and year. The Solar System inspector allows the start date to be specified and the objects will be moved to the position corresponding to that date.

The scale of the planets is centrally controlled from the Solar System builder to allow the planet scale to be changed maintaining the relative sizes of the planets. The choice of scale in the solar system is challenging if the goal is to show the entire solar system. Mercury orbits every 88 days and Neptune orbits in 165 years. The physical scale is similarly challenging. Often it may be necessary to have different scenes for inner and outer planets.

screen-shot-2016-10-27-at-5-47-16-am

PLANET SIZE PER 10,000 km

Sets the number of Unity length units per 10,000 km of planet radius. For reference, Earth has a radius of 6378 km, Jupiter 71,492 km.

START DATE

Specify the start date for the solar system. This will modify the positions of the bodies in the scene.

PREFABS

When bodies are added they are constructed from the prefab of the corresponding type. The prefab objects must contain NBody, OrbitEllipse and SolarBody components (SolarBody is used to hold the reference values of the orbit prior to scaling).

The Prefab may optionally contain a child with a Text component. If present the SolarSystem will insert the object name when the object is created. If the solar system is then made a child of a World UI Canvas then these text labels will be visible.

ADD BODY

Open a dialog to add a body to the scene. The Add Body dialog will appear:

screen-shot-2016-10-27-at-5-25-32-am

The type of body is selected by the first selection box. Each of PLANET/ASTEROID/COMET provides a selection box of well know celestial objects. If the desired object is not on these lists then the JPL_ASTEROID/JPL_COMET modes allow the parameters for a body to be located in the NASA/JPL database and then pasted into the dialog.

RandomPlanets

The RandomPlanets script is used to create a system of planets in random orbits around a central body when the scene starts. It allows control of the number of planets and a range for each of the orbital parameters. In order to allow more than one planet game object type it allows a list of planet prefabs to be provided and will pick randomly from the list for each planet creation.

This script is also a useful example demonstrating how to procedurally create and link planets.

Screen Shot 2016-08-24 at 6.29.12 AM.png

Number of Planets: The number of planets to be generated

Planet Prefabs: A list of prefab objects that will be used to create the planets. The prefab planet structure must match the examples in the prefab folder:

  1. Base game object with an NBody and OrbitEllipse component
  2. A child game object with a MeshRenderer to display to model for the planet.

Orbit Parameter Ranges: Min/Max ranges to be used for each of the orbital parameters of the planets.

Renderer Scale: Min/Max range of the local scale to be applied to the models of the planets as they are created.

Scripting Interface

Scene setup can also be done under script control. Documentation for the script interaction in HTML and can be found in html/index.html.

ThreeBodySolution

The gravitational interaction between three equal-mass bodies is a long-standing area of investigation in celestial mechanics. Over the past three hundred years a variety of solutions have been found. The Gravity Engine asset provides a set of these solutions, coupled with a special algorithm to allow them to evolve through regions where the bodies come very close to each other.

These solutions can be explored using the ThreeBodySolution script. They can also be found in the app ThreeBody available on iOS and Android. (The Gravity Engine asset derives from the work done on ThreeBody).

This component is added to a top-level game object in the scene. (Typically it is added to the GravityEngine game object).

ThreeBodySolution.png

Solution Set

Name of the solution set to select a specific solution from.

Solution

Name of the solution from within the solution

Body1/2/3

Nbody objects with mass 1 to be used in the scene. Their positions and initial velocities will be initialized based on the solution that has been selected when the scene starts.

Modifying the Gravitational Force

Screen Shot 2017-02-20 at 11.26.41 AM

Orbit due to 1/R force

The GravityEngine class allows for the force between masses to be changed – allowing the game developer to explore universes with non-standard physics. This can be done by selecting a different FORCE under the Advanced tab in the GravityEngine inspector. There are a number of built-in alternatives (the function of distance is indicated in parenthesis):

  1. InverseR (1/R)
  2. InverseR3 (1/R^3)
  3. ForceR (R)
  4. ForceR2 (R^2)
  5. Custom (requires a class attaching the force delegate interface be attached to the GE object).

The usual closed orbits that arise due to gravity are special. An object in a gravitational orbit returns to where it started from after one orbit. For other forces this is not true (with the exception of R^2) and the orbit will instead form a “spirograph” type pattern, the details of which depend on the force law. In reality in close proximity to a large mass the same effect happens in the real world – an effect due general relativistic effects. Famously, the orbit of Mercury when measured over decades is not exactly closed.

If the force is changed to something non-standard then the built-in orbit tools (OrbitEllipse, OrbitHyper, BinaryPair) will not show the correct paths. They determine paths with a the standard equations of gravity.

Defining a New Force

To define a new force requires a class inheriting MonoBehaviour and implementing the IForceDelegate interface. This interface requires that the force law and (optionally) it’s derivative be provided as methods:

  • calcF(double R) force function in terms of R only
  • calcFdot(double R) derivative of force with respect to R. This is optional. It is used if the Hermite integrator is selected. [To calculate derivatives symbolically you can use one of many online tools found on the web]

This class must then be attached to the same game objects as the GravityEngine script and the Force must be chosen as Custom.

Scaling

Gravity simulation deals with mass, distance and time. The units/scale for these elements in simulation is never in the standard units of physics (sec, m, kg). In general simulations rescale time, mass and distance to allow the computations to use numbers of “reasonable size”. The range of the number depends on the range of values being modeled. For example, in a Solar system simulation it may be useful to work in terms of “Jupiter masses” and set the mass of Jupiter to 1 and the mass of the Sun to 1047.56. (Wikepedia: Jupiter Mass).

The effect of scaling can be understood via Kepler’s third law:

G (m_1 + m_2) T^2 = L^3

The effect a change of the scale of mass and distance is summarized in Table 1:

Change Effect Change by 2x Change by 0.5x
Mass Orbital speed increases as mass value increases Evolve 1.4 x faster Evolve by 0.7x slower
Distance Orbit speed slows as distance increases Evolve 0.35 x slower Evolve 2.8 x faster

Gravity engine sets G=1 (to avoid multiplying by G in every force calculation).