Posted June 22, 2021 by Martin Bremer
This game was developed for the 2021 edition of the Game Maker's Toolkit game jam. Over 48 hours, Justin "Kabura" Neumann and myself faced the challenge of creating a game from scratch based on the theme "Joined Together". Justin would do all of the art, most of the animations, and some of the menu setup, and I would mainly focus on programming.
We started out with a basic brainstorming session. After a few initial ideas, we decided to go for something a little outside the box. The early concept for Orbitethers went through several iterations, but most of the central mechanics were already present even during that first meeting: the player controlled a circular object that would swing around a larger circle (a "companion", if you will) to which it was attached by a tether; the player would be able to shoot bullets that pushed objects in the direction of firing; bullets would spawn and fire randomly, like in a conventional bullet-hell game; collectible items would spawn around the map to give the player points and recover their health; and, lastly, there would be some sort of objects that pulled the companion closer, like gravity.
Thinking about the visuals of the game, we ultimately decided to keep it abstract, since deciding on a particular metaphor would likely make the concept and production phases for the art lengthier and could prematurely rule out possible changes in our plans. In other words, keeping it abstract, at least while exploring these mechanics, allowed us to be freer in experimenting with them and to just "follow the fun", as they say.
My approach for this exploration was to keep the codebase as flexible and modular as I could. The idea behind this was to minimize the number of dependencies between scripts and make it easier to progressively add new layers of complexity on existing classes. It was important to me that features were implemented and ready to test as quickly as possible.
I structured the system of interactions of the different elements in our game around interfaces. Some examples of interfaces in the project are: IPushable, ISpawnable, IDespawnable, and IBullet. Using these interfaces made it easy to trigger all the different behaviors of elements when they interact with one another while still keeping the logic of these particular interactions largely independent from the logic of other interactions.
After some preliminary testing of our system, I reached the conclusion that fitting Unity's native rigidbody physics with it would take too long ( a lot of undesired side-effects of it were constantly needed to be addressed). So instead, I decided to make all rigidbodies kinematic (to retain the possibility of using collision and trigger events in our code), and to manipulate the transform positions of our objects directly.
So I gave our moving objects a Move Velocity property and linearly interpolated it over time to mimic drag and decelerate objects. I am glad I made this switch, and I'm thinking I should always seriously consider custom-coding physics solutions where Unity's are more of an obstacle than a useful tool.
One interesting unintended consequence of this custom physics system was that our objects were not affected by timescale anymore. The problem here is that fairly early on we had talked about applying a slow-motion effect when the player lost the last of their health, before the game would restart. Again, the obvious solution was to create our own slo-mo effect.
In our Game Manager script, I created a little counter that would increment every frame and then loop back to zero when a predefined value was reached. Then it was just a matter of adding checks to all the classes supposed to be affected by the slo-mo effect: they would simply return if the Game Manager counter was equal to anything but zero. Essentially, what this did was give me the option to only call the Update function in those scripts every predetermined number of frames (which I imagine is analogous to what Unity's timescale does).
Not the most brilliant moment in coding history, but a nice little moment where I had to think on my feet.