Lessons in Structure

Posted On: 2019-07-08

By Mark

Over the past week, I have been reminded of the importance of establishing a clear data structure while working on a project. Although I had previously known of the importance of codifying a data structure for any given system, Unity's Component-based and designer-focused architecture makes it easy to be a bit cavalier about structure. Since this whole experience was a journey of discovery, I'll share how I learned these lessons in the form of a story:

Chasing Ambition

I had recently returned from a trip and was looking for something interesting to ease me back into coding. I have always had a fondness for Dark Cloud's weapon leveling system, and I thought I'd take a stab at implementing a (simplified) version in Unity. The idea was that this would be something I could do as a quick throw-away, and it was just focused on the development parts I enjoy (systemic interactions) so I was eager to start it up right away.

I started out by coding the interesting interactions (attaching, detaching, and absorbing) as well as the data model for the attachments and the weapons. It was simple, quick work*, but before I could test it, I had to implement some kind of UI. I wrote up some drag and drop components** and made a simple grid for an inventory. At this point, I thought I was ready to wire everything up - and that's where things really went sideways.

* Please don't read this as bragging: simple, quick, and untested usually means a buggy, naive implementation.

** Harder than it sounds - quite a bit of surprise research was required, covering topics from implementing the IDragHandler interface to understanding how the Graphics Raycaster works.

Facing Reality

In my haste to build the UI, I had completely overlooked modeling the inventory. No array of items, no add/remove functionality, no initialization logic to fill it with usable attachments. Instead I had a few slots that I'd manually created using Unity's designer, and a couple attachments that I'd manually placed inside them. Even though I'd spent the time and energy to correctly model the weapon and its attachments, all that work was unusable (and untestable) since there was no model for the inventory*.

By this point I had exhausted my enthusiasm for this throw-away endeavor and it was starting to eat into time I had intended to spend working on my main project, so I had to make a tough call. I dreaded both of the two extreme solutions - abandon the project immediately or completely rewrite the UI from scratch - so I chose a middle path: workaround the inventory by any means necessary, just to get the weapon side of things tested out. Several hours later, I had a fully debugged weapon upgrade system, and a shameful simulacrum of an inventory that barely held itself together.

* In case it's not clear, objects in the inventory can be attached to the weapon, and when they are unattached from the weapon, they need to go into the inventory: without an inventory, the attach and unattach logic won't work.

Reflecting

This whole adventure sharply reminded me that, in my main project, I had been focused on writing gameplay code and still hadn't touched modeling the underlying data. I resolved to put that issue to rest: I will work through any and all necessary data modeling and persistence before I resume work on user-facing elements of the game. As I write this, I am still in the middle of that effort, but I am hopeful that taking time now to get the model right will give me a better foundation on which to build future user interactions.

Animation demonstrating moving and absorbing weapon attachments.
Dragging attachments from the inventory and absorbing them into the weapon.
(All icons are from game-icons.net)

Hopefully reading through this process has helped you in some way. As I've seen firsthand, this topic is one that you can consciously know the right way to do it and still make dire mistakes, but perhaps this cautionary tale can be of some value nonetheless.