Orbit Mechanics

OrbitSketch.jpgMonths ago, around the start of DuskLight Studios, I wanted to create a game about flying around planets in orbit with each other. A game about exploration through space, adjusting your own orbit to move from planet to planet. I severely underestimated the difficulty of this.

Elliptic path

Orbit1Small.png

My first experiment in Unity included a single planet with a moon in orbit. The moon’s velocity was affected by the planet’s gravity, which varies in strength depending on distance to the planet. I couldn’t figure out the mathmatical formule to calculate the gravity’s pull, trying out faulty code I found online. It did result in an orbit, but it wasn’t right.

When a ship orbits a planet (and only that planet), it should be locked in an elliptic path. As long as it doesn’t accelerate in any direction, the ship will end up in the exact same position as it started at and eternally follow the exact same path. The first experiment did not achieve this, and I moved on to other projects to prevent wasting too much time.

Gravitational pull

A couple of weeks ago, I gave it another shot. I found a quite interesting link providing me with several different solutions to orbital mechanics in code.

SimpleOrbit.gif
A simple orbit

The Euler integration was easy to implement into a new Unity project. It started off in script; using the transform’s position, a velocity vector, and the gravitational pull to mimick the results. It worked, allowing me to iterate and improve upon the code.

Gravitational pull (g) equals to planet mass (m) multiplied by the square of distance between planet and ship (d^2): g = m * d^2

The function (present within the planet’s script) I currently use to calculate the gravitational acceleration:

public Vector3 GetGravity(Vector3 attract) {
        Vector2 delta = transform.position – attract;
        Return delta.normalized * ((mass * gravityConstant) / delta.sqrMagnitude);
}

Vector3 attract is the position at which the orbitting object is located.

Note that the calculations occur with Vector2 instead of Vector3, and that the square magnitude is used instead of the regular magnitude, both saving performance. Calculation of the square root of any number is much more CPU intensive than multiplications. Same goes for the Mathf.Pow(x) function.

Unity Physics

Achieving orbit is great and all, but I needed the code to work with the built-in Unity physics. That way I could include realistic collisions with planets and asteroids. I quickly ran into a couple of weird problems, though.

Note that all calculations should be run within the FixedUpdate, so it runs in sync with the Unity physics simulation.

I had to remove my own velocity vector and start using the Rigidbody2D’s velocity instead. Normally you’d use the function body.AddForce(gravity) to accelerate the ship, which I did at first. This resulted in a steady but weird orbit that didn’t follow the elliptic path as it should, leading me to believe that using forces for gravity is a bad idea. There was no way to really know how much velocity would be gained if I added a certain amount of force. Add to this that gravity pulls all objects equally, regardless of object mass, it proved I needed a different solution.

Instead of forces, I decided to affect the velocity directly. (body is the Rigidbody2D)

gravity = planet.GetGravity(transform.position);
velocity = body.velocity;
velocity += gravity * Time.fixedDeltaTime;
body.velocity = velocity;

CentreOfMassOrbit.gif
Defying laws of physics

This resulted in an almost perfect elliptic orbit, but the ellipse was a little off. It kept decreasing or increasing in size in a pattern. The issue here was the centre of mass of the rigidbody.

The centre of mass is automatically calculated by Unity, using the size and locations of the 2D colliders attached to the rigidbody. Changing the centre of mass to Vector3.zero solved the problem, but I also changed the gravity position to the centre of mass. If I ever change the centre of mass again, it should still work.
.

gravity = planet.GetGravity(body.worldCentreOfMass);

Asteroids.gif
Collisions

Now I can look happily at my near perfect elliptic orbit, watching my ship bump into asteroids and settle in a new orbit, occasionally crash landing on the planet itself and coming to a halt.

Google PlayGames + Google Analytics

For the past few days, I’ve been facing a frustrating issue;
Google PlayGames and Google Analytics are working against each other in Unity3d. I can’t get both working at the same time.

The Issue

Google Analytics has the priority, in an effort to record more data on the player gameplay.
Google PlayGames would be a really neat addition to add in leaderboards and achievements for the test players, since they quickly add low-dev-effort gameplay value, even in smaller games.

Both work by themselves, without an issue. I got a Unity Package ready for both to implement and use directly. But if I use one, I cannot use the other.

The problem is quite simple. Google Analytics uses a library called google-play-services_lib. This library contains a .jar file, which contains a variety of plugin files that are required for Google services.

Google PlayGames figured implementing the whole jar file creates a too big footprint, which I really agree with. But to fix it, they simply delete the library and replace it with .aar files, which are the files contained within the .jar file (Maybe not exactly the same, but the same plugins, yes). But guess who needs that whole library to function… Right, Google Analytics.

Possible Solutions

One solution that came to mind is to have GooglePlayGames use the whole library instead. But this doesn’t seem to work. There is no real error, but GooglePlayGames refuses to authenticate.

The second solution that came to mind is to have GoogleAnalytics use the .aar files instead of the library. But to accomplish this, I need to know what .aar files GoogleAnalytics requires before I can add them. I don’t know this yet, but if I find out, I could theoretically solve the issue.

The third solution is to use both the library and the .aar files. However, if both are included in Unity, it throws a building error of failing to re-package resources. This means that there are conflicting files, and thát means that there are plugins within the library that are also included in the .aar files. You can’t have two of the same things, in different formats, trying to compile.

To solve this, the idea is to manually remove certain files from the .jar library that are already included in the .aar files. However, to do this, I need to know exactly what files to remove from the .jar library, and I don’t know this yet. If I find out, it could theoretically solve the issue as well.

What’s next?

So without really knowing in full what files I need to remove and throw around, I can’t solve this issue. I’ve decided to, for now, drop it and return to it later. In the meantime, I hope the following issue reports might help in my quest:
https://github.com/playgameservices/play-games-plugin-for-unity/issues/1057
https://github.com/googleanalytics/google-analytics-plugin-for-unity/issues/109

Until then; away with GooglePlayGames. I’ll continue working on other matters.

The first of which: analyze my large generic modular code base to figure out what the internal dependencies are, and figure out if I could possibly sell these modules on the Unity Asset Store to get a little income, feedback and help out other devs a bit.

PlayStore Preperations

The past couple of days, I’ve been experimenting with the more (to me) difficult matters of app development. Getting an app on the PlayStore and incorporating third party plugins.
I succesfully got a Test App running on the Google PlayStore, as well as three working plugins. PlayGames Services for leaderboards and achievements, Google Analytics for recording gameplay events andPollfish for including surveys into my apps.
.
TestAppStorePage.png
.
By adding leaderboards andachievements to my prototypes, which in itself is not much effort, adds quite some gameplay value for testers to play the games.
By adding gameplay event tracking, I can see exactly at what stage players win or lose the game, or how many enemies they’ve blown apart, or how many times they’ve jumped up in a specific level. Really useful data for balancing.
By adding surveys into my apps, I can offer players to complete one and reward them with in-app content. As a developer, I get funds for each completed survey, and it’s not pushed into the players faces. My original goal with the survey plugin, however, was to gather feedback on the apps using surveys. This proved to be impossible, so Pollfish (and all other monetization) has to wait until I have an actual full-scale project in development.
I have an infuriating problem, however. Google Analytics requires a library to function, but Google PlayGames REMOVES this library automatically! This causes Google Analytics to no longer operate on Android. Difficult, but I’ll find some kind of work-around eventually.
All of this eventually leads to the features I need as a developer to properly let people test, and enjoy, the variety of prototypes I’ll publish on the PlayStore. Hopefully leading to more detailed feedback, and eventually a better playful experience for everyone.