Orbital Mechanics in Unity Game Engine for Augmented Reality

[Total: 6    Average: 4/5]

In this post I’ll go over implementing basic orbital mechanics simulations in the Unity game engine as well as an approach to scaling the simulation for Augmented Reality applications. Unity is a great tool for prototyping games but also for animating physics models. The physics gets more interesting when you can watch the all the interactions over time and see your formulas doing their work.

I’ve been developing games for over 30 years and as a game developer, playing with gravity simulations has been a go-to game design mechanic. I’ve always been fascinated with gravity. Whether it’s playing with scaling gravity in a game, riding mountain bikes or shredding at the skatepark, gravity is fascinating and fun to play with. I recently got the opportunity to work on an Augmented Reality, or AR, game prototype that uses orbital mechanics as a gameplay mechanism. One of the issues with AR applications is that you need to be able to let the user scale the models so they look the appropriate size for the location they are placed in the real world, relative to the user. For example, there’s room to place your virtual object in a far corner of the room, but it may appear too small from where the user is located. If the open space in the room is too close to the user, then it will appear way too large and spill over the edges of the display. In most applications you can just set the scale, keep it constant, and move the camera in your simulation order to render the scene at the appropriate size. In AR the user is the camera, they physically move closer or further from the object. So it’s not something you can set in your code and be done with. However, with our solar system model it not only has to be scaled in size visually but the physics model needs to be scaled as well.

Unity has some awesome built in physics modules that include gravity simulations, but they are setup for simulating gravity for a small object on a single enormous planet and not for orbital mechanics. So you need to add some of your own algorithms for simulating the interaction and motion of multiple planets. For my prototype I found a great package for \$6.99 on the Unity Asset store, Gravity and Orbits Solar System. It’s a great starting point. Although there are a lot of ways this code could be improved with regards to design and style it’s a great functional example of an animating solar system. However it does not support scaling the solar system, which is required for AR applications.

The approach used for the orbital mechanics motion is this:

1) Generate forces applied to your objects (planets in this case) using this algorithm:

a) directionForce = (SunPosition – PlanetPosition) / distance;
b) forceValue = (SunMass * SatelliteMass) / Math.Pow(distance, 2);
c) force = GFactor * forceValue * directionForce;

2) Then apply the force to the RigidBody component of your Unity GameObject using the RigidBody.AddForce() method.
3) So let the Unity RigidBody component determine the movement and position updates from the force calculated above.

The next problem is to be able to scale your solar system. The size of your planets, their distance apart, initial forces and mass all need to be scaled appropriately.

In Unity, you might approach scaling your entire 3D world by making every GameObject (one planet in this case) a child of a single “universe scaler” GameObject where you set the scale in one place and all the children in the hierarchy inherit that scale, thus appearing the right size in relation to one another. The issues with this approach are that it doesn’t support scaling the physics simulations, (mass, initial force, etc.) and it also doesn’t maintain any scaling you’ve done in the Unity editor in order to differentiate your models (e.g. the different sizes of the planets) as is done in the Gravity and Orbits Solar System package. The pre-scaling done in the editor is just overwritten by the inheritance operation so all your planets based on the same Unity prefab (base model) will be the same size when scaled at runtime. The solution to this is to add a scaling script to each Unity gameobject that handles the scaling of the size of the model (transform.localScale) as well as scaling the mass of the Rigidbody component. It’s important that you scale the mass by the scale factor cubed.

newMass = originalMass * scaleFactor3

In C# code it would look like this:

// scale the model’s transform (its appearance)
{
transform.localScale = originalScale * scaleFactor;
// scale the mass
Rigidbody rb = this.GetComponent<Rigidbody>();
if (rb)
{
// set mass
GetComponent<Rigidbody>().mass *=
(float)Mathf.Pow(scaleFactor, 3);
}
}

The initial speed and position offset need to be scaled as well.

satellite.GetComponent<InitialSpeed> ().speed =
InitialSpeedConstant*scaleFactor; Vector3 position =
centerPlanet.transform.position + positionOffset*scaleFactor;

Also if you’re using the Gravity and Orbits Solar System package don’t scale the initial direction as it’s unnecessary and will scale the initial force inappropriately.

There’s lots of ways to achieve the same outcome but that’s the approach that worked for me.

Unity is a great prototyping tool and adding an animated simulation for your orbital mechanics project, that works on most any platform (PC, Mac, iOS, Android, etc.) will make it much more exciting and interesting to view. I would recommend the Unity Game Engine for use in modeling and animating any physics project. It’s free to download and really very easy to use.

I’ve been developing games for over 30 years and as a game developer.

2 replies
1. jedishrfu says:

Great insight! I especially liked the description of scaling factors and how they a codependent on one another requiring a more nuanced program design.

Unity is awesome, we did a unity simulation of Challenger Deep where the user could fly through the canyon using an Oculus Rift for one implementation and similar code for an Android tablet implementation.