The game can be found at:
- Card-based gameplay and combat system
- Tactical grid based movement in combat
- Dialogue system with branching paths and choices
- Heavy use of menus and overlapping UI systems required handled of multiple UI states and complex input detection
- Developing UI solutions for save and load systems
- Developing generic UI components that can be used to trigger effects on various UI elements, such as scaling effects or changing colours over time.
- Worked closely with the Unity addressable system to load and unload assets effectively
- Worked closely with the UI artist and game designer to discuss UX flows, ensure things can fit within our timeframe, and discuss technical limitations for proposed designs.
- Working with a localisation text system within the user interface, ensuring that text is properly translated and auto sizes across languages.
- Wrote in-depth write-ups of proposed systems before implementation began, sharing this with the programming team to receive comments and feedback to ensure things are ready to fit into existing systems.
I joined the team on Xenotheria while it was mid-stage in development. A lot of systems were in place, however the game was using simple placeholder UI and did not have many UI systems in place. My role on the project was to work closely with the UI artist and game designer to implement UX designs and art assets into the project, and develop the systems behind these menus.
While my main role was UI work, I also did work on the back-end of some of the systems I was implementing menus for, such as the deckbuilder. It was very important to keep the back-end separate from the UI when possible, as an ideal system would work without the UI present. With this being a game that was heavy on UI, it was hard to find a way to achieve this for some systems. For example combat, which cannot be interacted with at all without the user interface being present. My main method for avoiding dependencies was using events and listeners. Rather than calling UI script methods directly, logic scripts would invoke an event which could then be listened to from the UI script to update or display information when needed. This also allowed us for extra flexibility outside of UI, as we could listen for these events in any context.
As I was working on a smaller team, I did also find myself being flexible and working on more generalist systems outside of my focus as UI engineer - offering help when it was needed.
General UI Work
My main focus was implementing UI assets using the Unity UI system, and designing my own code systems that were forward compatible and flexible, able to be used across the project. Before implementing any systems, I would discuss with the UI artist and game designer, letting them know of any potential problems or limitations when translating the design to an in-game menu or element. I would also give general feedback on the design and visuals at this stage.
After discussions with the artist and designer, and ensuring we have everything we need, I would create detailed technical write-ups, laying out my plans for which scripts would be needed, their methods, and my general thoughts towards the system, its purpose, and how it would interact with existing and future planned system. This would then be shared with the tech team for further comments and feedback, iterated upon, and then being implemented in-engine.
When working on UI systems, creating generic systems and abstracting out as much as possible was very important. It was important that these systems can be re-used across the project. As an example, the deckbuilder, which has a grid of cards, does not have this grid baked in to the deckbuilder but instead the grid is a separate element, allowing it to be used elsewhere such as the discard/draw piles in combat.
UI art by Aydin Gurer. Environment art by Sam Heisler. Character and card art by Chris Gardula.
Deckbuilder, Crafting, and Upgrade System
One of the big systems I worked on was the development of both the front- and back-end for the card management systems - the deckbuilder to create a character deck, the crafting window to spend in-game resources to create new cards, and the upgrader to add new effects to existing cards. All of these systems had to interact with one another and react to changes (for example, adding new cards to the card collection view when one is crafted) but it was also important that they did not have direct dependencies on one another. As mentioned above, events and listeners came in handy here and allowed me to create links between scripts and systems without making them require one another. This would actually prove useful later in development as we made some changes to the deckbuilder, which resulted in needing to separate the systems out more.
Working with Perforce and Swarm
Outside of my work within the game itself, the project also required me to become familiar with Perforce version control and Swarm code reviews. We use the P4V GUI to interface with Perforce, which was vastly different from my usual workflow with GitHub and thus required me to adapt when I started on this project. I quickly became familiar with working with changelists, and over time found myself using them effectively in order to split my work into smaller tasks and easily separate out any changes I was making to scripts. As a team, we also used Swarm to submit our changelists for review. I found this to be a particularly useful step in the process and allowed us to easily comment on each other's work and catch small mistakes that may have been made.
In-depth documentation of systems
In order to make sure the non-technical members of the team could easily work with the systems we created, we found it important to communicate clearly how things were set up, how prefabs and data objects could be found and edited, and what should be avoided. We used Notion to have our documentation in one place for anyone on the team to find and refer to.
When it came to our tasks, I would write up detailed breakdowns of what scripts and systems I would need before getting started with the code. I would send this through to the tech team as a Google Doc so we could all comment and collaborate on the document, discussing what does or doesn't work, and ultimately deciding on the best approach before getting started. I found this a particularly useful step in the process that sped up my work in-engine significantly and let us catch any major issues - such as unnecessary dependencies, redundant code that already exists in the project, etc. - before they appeared within the project.