Kalidax Farming Program
A Unity farming tycoon with a custom tool for quickly adding aliens!
A Unity farming tycoon with a custom tool for quickly adding aliens!
Our game Kalidax Farming Program is set on an Alien Planet where the player can merge aliens to create new ones of a higher tier. There will be many aliens in our game all of which have many parameters, so I offered to create a tool for the designers to easily create new aliens.
🔵 Roles: Tools Programmer, Gameplay Programmer, Game Designer
🔵 Collaborators: Sebastian Mena Andrade, Emily Barraclough, Brady Anderson, Sarah Chambers, Ashton McKenzie
🔵 Year: 2023 -2024
🔵 Timeline: 6 months
Ability to create new aliens quickly - So designers can spend more time tuning parameters
Visually appealing UI - So the information is understood and enticing to look at
Focus on edge cases - Even if a mistake is made, designers can know what it is and how to fix it
Game Trailer
Custom Tool Showcase
As stated with my design goals for this project, I wanted a quick way for designers to add Aliens into the game. Each alien would have universal data like their name and tier so I created a custom inspector tool to display the same information to the designers as friendly and approachable as possible. The After screenshot redraws the entire inspector call, so I call every variable in the order I want them to be displayed, and add a visual image as well as buttons to rename and delete the alien.
As learned from my Moving Platforms Tool, the team will use your tool in ways you did not intend. With the Alien tool, I thought of possible edge cases where designers may have made a slight error and guided them in the right steps to fix it through warning boxes.
Below is the tool designers will use to create aliens in our game. After creation, they can edit the alien's individual input data. I upgraded the visuals to provide much more feedback to the designer.
The Alien Tier dropdown has a different colour based on the tier selected, and the same colours are seen in the database below it for visual cohesion.
The Alien Database is organizable by ID or by alien tier, and aliens are also searchable through names, a great tool if we have many aliens and want to search for a specific one.
The database shows a visual image of the aliens so we don't need to remember the names!
More edge cases have been added, a warning message is sent if the designer is trying to create an alien with the same name and tier as an existing alien in the database.
Below I describe other features I programmed in our game! Click the dropdown to view its contents.
Incubation Pods are machines that take in seeds, incubate them for some time, and then output an alien once a certain amount of days have passed. I used states to dictate their behaviour each day and an enum value to store the current state.
Some players were confused about nothing happening when they clicked the "Add Seed" button, so I made text float up if they didn't have any seeds to remind them that this machine requires seeds to be placed.
Each state also has an associated colour with it so players don't need to interact with the pod every time to understand its current progress!
Players can interact with the Incubation Pod machine using my custom Interaction System I made in conjunction with my Dialogue Graph System for Unity.
Gene Splicing refers to our main mechanic of merging two of the same alien together to create a bigger version of it! Each alien has their own tier which is set using the custom tools. Combine two tier 1 Sprogs to get a tier 2 Sprog.
Each Alien is under a "AliensInWorld" gameObject in the hierarchy, so when a player opens this Gene Splicing Menu, I create a list of all the child objects and get their "SO_Alien" component to display the icon of the alien and their tier.
To create the grid that stores the aliens, I used Unity's Grid Layout component and make as many buttons as there are aliens in the world. The buttons take the image of the alien, and when an alien is already selected they will appear darker to communicate to the player that they cannot select the same alien.
Players can interact with the Gene Splicing machine using my custom Interaction System I made in conjunction with my Dialogue Graph System for Unity.
In Kalidax, players go through many days on the planet and with each day the scene transitions to another for the results, then back to itself. I needed a way to save the current status of the scene so when it reloads, the player's progress would have been saved. To do this, I use Scriptable Objects to save data between scenes.
The problem with using Scriptable Objects for saving data is that they cannot save Transforms, gameObjects, or scripts attached to scene objects since these components are specific to this scene. When we jump to a new scene, those fields become "Missing" and we no longer have access to what we tried to save. The solution I implemented was a bit of a workaround - where instead of saving the gameObject or script, I would save persisting data such as a Boolean List, a class List, enums, etc.
Since there are only 4 of these machines throughout the entire game, I make a class array with a size of 4 and in the class I have variables to:
Declare the index so we can get a reference to the in-game incubation pod associated with it,
Store the state
Store the days left when it starts incubating
Store the type of seed the player added in.
I also have a separate bool array to declare which incubation pods have been purchased. At the start of every day each incubation pod checks the data associated with its ID and sets its state based on it.
Each grass tile can be either cut or not cut. If the seeds are cut, there's a chance for them to regrow the next day and their sprite is changed. At first, I tried to save each grass tile's script between scenes so I could simply get the variable if they're cut or not and assign that to the new scene's grass tile. As mentioned before however, Scriptable Objects do not support that Serialization and cannot carry scripts between scenes as they are unique to the current scene. I instead used a bool array the size of how many tiles are in the scene. I return true if the tile is cut, and return false if the tile is not cut. Then at the start of every day each grass tile checks to see if the number associated with it is cut or not cut and updates its sprite and variable based on the bool array.
At the end of the day, I wipe out the previous day's bool array and re-initialize it with the new day's information. I then find all the objects with the <GrassTile> script and put them in a temporary GrassTile array, and then sort the array based on the grass tile's x and y positions in the scene. This was the key to keeping the order in the array consistent every time! Without sorting the array I would not be able to accurately retrieve the data each new day and the seeds won't have their own data the next day.
After the players end each day, they are sent to a new scene that shows them statistics on their performance that day based on different categories. The first couple slots display profits from selling resources, and the next 3 display any losses deducted from their wallet. I use Lean Tween to animate each component from the left side of the screen tot he middle for a more engaging view! I also made use of Unity's Vertical Layout Group to get each component spaced uniformly from each other.
I updated the end-of-day results with the earnings players obtained and used during that day. I keep track of all the player's purchases each day in an int array[], and if (for example) the player purchases an incubation pod, then the amount spent will be added to the [3] index in the array. The int array starts at index 0 at the top (sold items), and ends with index 5 at the bottom (total). Then when the players end the day, at the start of the scene I assign the numbers based on the stored int results. When a new day occurs I wipe out the int array to start fresh.
When the player ends the day the screen fades before changing scenes instead of being an instant transition.
Behind the scenes, when "Yes" is selected the game calls a public function to start playing a fade animation in the UI. Then when the animation reaches its last frame, an event is played that loads the new scene.
When the scene starts, a fade-out animation automatically plays instead of instantly plopping the player into the world. These smooth transitions keep players immersed in the experience and enter a flow state between days.
Audio is so important to any game even though it's generally disregarded til later on in development (at least from my past experiences). Below is how my Audio Manager System appears in the inspector. Our sound designer can quickly add sounds, and multiple clips to randomize which sound plays, and adjust features like volume, pitch, and loop. I also have a separate list for background music where I use an enum to choose the theme.
If we transition to another scene and that scene has a different track in the "Background Music Select" gameObject, it will fade out the previous audio, and fade in the new audio. If that scene has the same music track selected as the one that's currently playing, it will continue to play and not restart. I've been focusing my attention on creating new methods that allow sounds to fade in and out, pause, stop, play, and more! Here are some options for playing background music:
I've also created a pause menu where players can access different audio controls for the Master, SFX, and Music sounds. This was done by creating an Audio Mixer (which comes pre-built with Unity), and then assigning the different effects to one of these sounds. The Audio controls in the pause menu will then read the original data and save it if the slider moves, affecting all sounds that are assigned to these audio groups.
Since I set the TimeScale to 0 so all in-game events are frozen, the regular deltaTime was obsolete here. To solve this, I used .setIgnoreTimeScale(true) through LeanTween's library which works when the time scale is set to 0, thus the animations played smoothly! The "Controls" menu displays a graphic I created using photoshop to teach the players the different buttons required for play. I decided to show the entire keyboard to help players visually see where the buttons are that they need to press rather than having to recall where they are on the keyboard.
During the duration of the 8 months development time, our team conducted 3 playtest sessions to gather user feedback and observe common pain-points from each play tester. We each gathered at least 2 play testers and observed their play experience, writing down specific phrases, noting the order of execution, and general play patterns. Then afterwards, the team identified common threads including bugs, UX complaints, and enjoyability complaints in a google document with some steps to solve them! Below are some of the features I helped improve based on this feedback.
I added temporary animations to the aliens in code since due to scope we could not use the bone structures our artist created for animation. These temporary animations were achieved using the LeanTween package for Unity. This code sample makes the aliens squash and go back up to simulate breathing. We also have an animation to flip the sprite-like Paper Mario when the aliens turn the other way. This makes the aliens feel more alive with the simulated breathing instead of being a static image, making the player more immersed in the world.
Problem: Players did not know what button to click to purchase an incubation pod.
Solution: I added text that displays the current day in the UI, and added the button needed to purchase the incubation pods so players know what action to perform.
Problem: Players were confused that nothing happened when they pressed the "Add Seed" button.
Solution: I added floating text that dissolves if they do not have any seeds, telling them they cannot currently perform this action.
Problem: Players did not know which grass tile they were cutting since there was no visual feedback.
Solution: I created a script that creates an outline of any collider component, so I used it on the grass tiles to make a white border to outline the current tile they are about to break.