As described in the previous blog post, I decided to learn many 2d features in Unity via the process of porting a game jam title I made called Grit Grumble’s Happy Factory from GameMaker: Studio to Unity 2018.3. This came with its own headaches and celebrations, as some tasks proved to be very tedious to replicate or find information on whilst other tasks proved to be much simpler to resolve with Unity’s pre-built systems. I needed to find many equivalents to particular procedures I performed in the game’s original development, but I also wanted to add some new features in the process.
The first task in setting up the Unity environment was to import my old assets. I wanted to improve the workflow from my previous work in GameMaker not only for the sake of efficiency, but because it was practically essential as a time saving measure in Unity. There are a number of parameters in each graphical object that need to be normally adjusted manually to suit the rendering style and proportions of each image in relation to the Grid Size used in Unity, so using an automated process for importing saved me incredible amounts of time.
I decided to import all my animations into Aseprite, tag the frames within each file to differentiate animations for the animator component, and use an AnimationImporter plugin to automate the process and update my animations whenever I modified them in Aseprite. What I liked most about this method was that if I were to abandon ship on the porting process that I could use LazyLoad to do the equivalent task for GameMaker Studio, thereby making it easier to develop and edit animations for that engine as well.
The next challenge was to learn precisely how to use the Animator component for sprites. For simple animations, I was able to use a combination of parameters and transitions to accomplish this, setting the transition time to zero for instantaneous changes. Of course, since my conveyor animations have at least 33 different states, this was certainly not the most efficient solution at larger scales with such a graphically-programmed interface. The solution was to use a blend tree with a 2D Cartesian grid to automatically change the animation depending on the proximity a conveyor was to its neighbors and the direction that it was moving. Each motion that I wanted to animate was given its own defined parameter values required for its display. The last challenge was to have all my conveyors animate in synchronization which I accomplished by having a global variable track a time to be mirrored to each conveyor belt in the scene.
The remainder of my assets were relatively easy to import with the exception of Tiles and UI elements, which both have their own unique challenges: Tiles need to be mapped to a Grid component as well as the world grid to behave properly and UI elements use a different type of graphic renderer (Image instead of SpriteRenderer). Because Unity animation clips target components as a means of changing their displayed sprite (or whatnot), the targeted component for every animation used in the UI needed to be changed from SpriteRenderer to Image.
Because I intended to work in a pixel-perfect rendering environment, I needed to import the 2D Pixel Perfect package from the Unity package manager. This comes with a pixel perfect camera that ensures that all graphics render based on pixels rather than anti-aliasing techniques with the exception of some UI elements, which in some cases I had to manually adjust their filter mode to have their graphics render naturally.
I made several improvements to the graphical representation of elements. The paint machine is no longer a large vent but rather a pulsating machine that displays the colour of paint it will output. I also created a matter former machine in the form of a Monkey, which took a full day to animate and creates new types of toys for the factory.
The wall tiles were modified to accommodate different factory shapes. They use Rule Tiles in the editor to automatically determine their form, which makes the matter of placing them in context fast. The tile system also features a collider system, which made the process of fencing off the play area simpler than manually placing collider walls seperate of these tiles.
The UI was also graphically improved from its predecessor, with a cleaner interface and more visually readable buttons. I still have yet to implement the hover-over text from the GameMaker version, but I have created a system of pages that I hope to exercise in future builds which will allow players to flip through multiple options for machine creation and factory management.
Grit’s text has been somewhat imported, with a cute speech bubble to replace the black box for text. I’d ideally like to make this chat box flexible for larger swaths of text, but I haven’t determined how best to do this graphically as of yet. I also intend to include a more intelligent tip system for players.
The object creation reticle now accurately aligns with the game grid and allows for users to erase all objects in the game context with the exception of floor space. Players can also fly around a much larger factory context with camera controls. The movement is currently defined by the window border, although I hope to implement a less intrusive means of navigating play space… at some stage I hope to port this over to android, so simply using arrow keys may not be the best solution.
There are a few remaining bugs to resolve with my import of the code from GameMaker to Unity as not everything has its directly obvious equivalent implementation. The conveyors don’t behave as effectively as they did in the original (although I have a fix prepared for this), and the workers and matterballs have odd ways of behaving when in direct contact with colliders. I also have not implemented the following features:
- The ‘falling machine’ mechanic, where workers would be crushed beneath newly instantiated machines
- The ‘beer’ and ‘gas’ machines, which had unique behaviours when interacted with by workers
- The title card
- Worker selection and commands
Otherwise, the gameplay features from the original game seem to have been imported successfully. I spent about three weeks time working on what I have today in comparison to the original build that was accomplished in three days. I think this stands as a testament to my familiarity from one engine to another as well as the relative speed it takes to create a script in GML versus C#; the former features many shortcuts targeting 2d game development whereas the latter is more rigorously designed and controlling over where and how its assets are used.
New features include the Monkey, which forms matter into toys, a larger factory setting, and fire: the threat of combustion to force a more tense environment. I hope in the future that the game extends from its current state of economy management to a place where both financials and the state of the factory create a tension and challenge for those hoping to succeed in accomplishing a level’s goals.
If I continue developing Grit Grumble’s Happy Factory and properly develop the mob-management features I intended to when I first started development on this strategy game, I believe it stands to carve its own niche among comparable titles in its genre. Although Unity came with many of its own frustrations, I believe after spending the time to port this game I am finally at the stage where I feel comfortable developing any game I normally would create in GameMaker in the Unity engine and that I have the capacity to resolve the remaining porting issues in this game.