Online docs now have updates for version 1.5 (coming soon to the Asset store)
New in 1.5:
Trajectory prediction: N-body look-ahead simulation to show future paths of objects.
Bug fixes/minor enhancements:
- OrbitPrediction for systems that use non-default units (e.g. ORBITAL or SOLAR) has been corrected.
- Kepler objects now correctly handle a timeZoom change. They have been added to the AddDeleteTester demo scene.
- Kepler objects can now be added via script.
- A method to get double precision speed and velocity for an object has been added: GravityEngine.GetPositionVelocityScaled(). This is demonstrated in the Units-EarthOrbit tutorial via the LogPositionVelocity script (pressing L will log position and velocity to the console)
- OrbitData parameters have been made public in the OrbitPredictor to allow their access via scripts.
Code Documentation: http://nbodyphysics.com/gravityengine/html/
- 1 Overview
- 2 Tutorials
- 3 Package Overview
- 4 Tutorial Scenes
- 5 Demo Scenes
- 6 Documentation
- 6.1 Gravitational Objects
- 6.2 Gravitational Particles
- 6.3 Collisions
- 6.4 System Builders
- 6.5 Modifying the Gravitational Force
- 7 Scaling
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/
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
There are three key classes involved in adding gravitational evolution of objects to your Unity project:
- GravityEngine – the script that performs all the physics calculations and updates object positions in the scene.
- NBody – a script attached to all bodies to be controlled by the GravityEngine. Used to specify their mass and initial velocity.
- 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
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.
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
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.
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 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:
- Explode or Bounce (based on contact velocity)
In each case the physics engine is updated as required and momentum and energy are conserved.
|Overview||Central star with an orbiting planet and particle ring.|
|T1 Binary Pair||Create a binary pair of stars that orbit their center of mass.|
|T2 Orbits||Create elliptical and hyperbolic orbits. Demonstrate N-body vs Kepler evolution|
|T3 Collisions||Demonstrate the ways collisions can be handled in Gravity Engine.|
|T4 Particles||Setup particle systems (box, orbiting ring)|
|T5 Orbit Prediction||Two body orbit prediction with the OrbitPredictor component.|
|T6 Trajectory Prediction||Full N-body look-ahead modelling of trajectories with time markers.|
|Units - Earth Orbit||Spaceship and space station in low Earth orbit with units in km.|
|Solar System Inner||Show how to create the inner solar system in AU units.|
|3BTrajectory||Three body solutions with a spaceship and trajectory prediction.|
|AddDeleteTest||Interactive add/delete of massive, massless and Kepler orbiting bodies.|
|ForceCustom||Demonstrates a custom (non-gravity) central force and its effect on planets and particles.|
|Force Inverse R||Shows a 1/R (vs gravity's 1/R^2) force.|
|FrameRateTest||Automatically add massive bodies until the frame rate drops to 58 FPS. Reports N.|
|OrbitDecay||Shows how a simple add on script can create decaying orbits.|
|RandomPlanets||Scene which auto-creates a series of planets in random orbits.|
|SolarSystem Inner||Model of inner solar system|
|Solar System Outer||Model of outer solar system.|
|ThreeBodies||Shows the three body configuration generator.|
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:
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:
- DIMENSIONLESS: Arbitrary units used directly in the force calculations. When selected the inpector allows Mass Scale and Time Scale to be varied.
- SI: Units are in m/kg/sec. See Real-Unit scaling below.
- ORBITAL: Units are km/1E24 kg/hours. See Real-Unit scaling below.
- SOLAR: Units are AU/1E24 kg/years. See Real-Unit scaling below.
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.
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.
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.
Trajectory prediction control in the Gravity Engine component works in tandem with Trajectory components added to NBody objects in the scene. Instructions for the configuration of these is provided in more detail BELOW(link) and in Tutorial 6(link).
Trajectory Prediction (Checkbox)
If enabled, the GE will simulate the future progress of all massive and massless bodies in the scene for the time indicated by “Trajectory Time”. NBody objects that have a child with a Trajectory component will have the future path rendered via their Line Renderer components.
If there is a call to ApplyImpulse or ResetTrajectory then the future evolution will be re-computed.
The time into the future that all objects will be evolved for to determine trajectories for those objects with Trajectory components.
Frames Between Resets
The number of frames that must elapse before a new ResetTrajectory (directly or via ApplyImpulse) can be performed. Since a trajectory re-computation requires the scene be evolved for the time indicated by “Trajectory Time” this can be a CPU intensive activity. Imposing a non-zero limit ensures that this does not occur too often.
Canvas for Text
The Trajectory component can optionally add labels to indicate the future time along the trajectory. These text components require a World View Canvas in the scene. This field provides the reference to the Canvas for use by the Trajectory components.
There are a number of possible algorithms for gravitational evolution. They vary in accuracy and computational complexity.
- Leapfrog: The best default choice. This is a computationally cheap algorithm with a fixed time step that conserves energy well.
- Hermite: A variable time-step algorithm that will spend more CPU cycles when objects get close to improve accuracy.
- 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.
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.
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:
For a scene with real-world units it is:
Mass is specified in dimensionless units. A value of less than zero will be set to zero.
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.
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:
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.
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:
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:
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.
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.
Selects whether the size is specified as semi-major axis (a) or distance of closest approach (p).
- Size: specified by either the semi-major axis (a) or the point of closest approach, the periapse (p).
- 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
- Orientation: Celestial mechanics uses a specific choice of Euler angles defined as follows:
- Ω (longitude of the ascending node)
- Angle of inclination
- (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.)
Defines the objects initial position on the ellipse in degress (0..360).
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.
Hyperbolic orbits by definition have an eccentricity > 1.
The same as OrbitEllipse, with the requirement that eccentricity be greater that 1.
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.
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.
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].
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)
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).
The Trajectory component shows the future path of an NBody object based on a simulation of the entire scene projected into the future. It handles cases where there are multiple massive objects interacting. It is more computationally intensive that an OrbitPredictor – which uses a two-body model of the interaction.
The Trajectory component works in conjunction with Trajectory configuration options in the Gravity Engine. It is attached to a *child* of an NBody object – since it requires a Line Renderer and material. Adding a Trajectory component will automatically add a Line Renderer component. In order to see the line in the scene a suitable material must also be added to the object.
The parameters for a Trajectory are:
Min Vertex Distance
Minimum distance between positions required before a new point is added to the Line Renderer.
Maximum number of points to be added to the Line Renderer.
Time Marker Prefab
A trajectory may optionally add an object at fixed time intervals along the trajectory. This element provides the prefab used. The objects added will be oriented so that the z-axis of the object is aligned with the path of the trajectory.
Time Mark Interval
The interval between time markers on the trajectory.
Time Text Prefab
A time label can be added to the time markers. This requires a prefab object containing a UI Text component. In addition the Canvas field in the Gravity Engine Trajectory configuration must be configured with a Canvas that has mode World View.
Align Text to Traj.
If checked the z-axis of the Text prefab will be aligned with the Trajectory.
This script provides a simple per-frame reduction in velocity and results in the decay of an object in orbit.
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.
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.
Specifies the velocity of the center of mass of BinaryPair.
See the description of fields in OrbitEllipse above.
Adding a FixedObject component to an NBody game object creates an NBody object that has a mass but remains at a fixed position.
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.
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.
DustBall implements IGravityParticlesInit and is used to initialize a sphere of particles all moving at the same velocity.
Initial velocity of the particles in the dust ball.
Radius of the dust ball.
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.
See the description under OrbitEllipse, above.
Defines the width of the particle ring as a percentage of the radius.
Initializes particles in a 3D box.
Size of the X, Y and Z axes of the box. Box will be centered at the transform position.
Initial velocity of dust particles
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 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.
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.
Defines the width of the ejection cone in degrees (from center axis to outside).
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.
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 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:
- Collider IsTrigger Enabled
- Rigid Body IsKinematic Enabled
- Rigid Body Mass set to 0 (will appear as a very small number in inspector)
- RigidBody UseGravity Disabled
The NBodyCollision object will handle the trigger events from the collider and interact with the GravityEngine to achieve the desired outcome.
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.
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.
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.
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.
Specify the start date for the solar system. This will modify the positions of the bodies in the scene.
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.
Open a dialog to add a body to the scene. The Add Body dialog will appear:
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.
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.
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:
- Base game object with an NBody and OrbitEllipse component
- 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.
Scene setup can also be done under script control. Documentation for the script interaction in HTML and can be found in html/index.html.
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).
Name of the solution set to select a specific solution from.
Name of the solution from within the solution
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
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):
- InverseR (1/R)
- InverseR3 (1/R^3)
- ForceR (R)
- ForceR2 (R^2)
- 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.
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:
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).