Structs (or, creating our own custom containers)
This is just an article on something I’ve found useful time and time again when creating game systems. While I won’t pretend to understand everything there is to know about structs, I hope I can provide an overview on what they are and why you should consider using them (if you aren’t already).
There might have come a point in your programming when you need to package up and store multiple variables together, something which, say, a list of one of the standard variable types is unable to provide. For example, let’s say we want to keep track of what a player bought at an in-game store. We could just do this by adding the names of the item’s purchased to a list of strings:
This would work if all we ever need to refer to is the name of the item bought, but let’s say we also need to know how much the item cost. Since a default variable types such as strings, floats, ints, and bools don’t let us store this additional information and associate it with the same element in the list, we can instead create our own containers using structs to quickly and easily achieve this. When creating a struct within one of our classes, I’m essentially creating a blueprint for what, in our case, an item on the shopping list is (namely, the variables it contains). I’ll write this out first, then give a bit more of an explanation:
First, I’m giving it the System.Serializable attribute so I can see the struct in Unity’s inspector if I’d like. Then I’m declaring a new public struct called ‘Item’ and declaring the variables it consists of (a public string called ‘itemName’ and a public float called ‘itemPrice’). The ‘constructor’ which follows isn’t strictly necessary, but at the very least it can be helpful when we need to quickly and easily create instances of our struct:
We could now set this up so that each of the items in the store has a public Item variable, and we can even specify these details within the Unity inspector to define, say, one item as an Iced Coffee costing 1.67 and one item as a Bagel costing 0.70. When the player clicks to purchase these items, these structs and the information contained within them can be passed onto a list of Items located on the player’s script/class:
With this all in place, we could iterate through each of the elements in this list using a for or foreach loop and add up the itemPrice values to find out how much they spent and by extension how much money they have left. We could also use this a loop or perhaps a LINQ method to check to see whether they’ve bought an item with a particular name, or to pick out the items that were, say, less than 1.0f in price. I appreciate this isn’t a terribly exciting example, but I’ll move onto an example of a more gamified example:
Let’s say in my game I want a random sprite from a list to move from one end of the screen to the other, perhaps as some sort of visual and auditory distraction. Again, we could just create a list of sprites and then randomly pick from that list, but let’s say we also want to determine how fast each sprite moves, whether it’s flipped, or perhaps what it’s color or transparency is. We could create a ScriptableObject to create each of these in the assets folder, but perhaps we want something quicker and simpler, located on the script where it’s used. A list of a custom struct could let us store and specify all of this information in Unity’s inspector for the game to make use of:
We could now create a list of these on some sort of moving sprite manager script, specify the details of the possible moving sprites in the inspector, then let the manager pick out one of these at random and send the details to a newly instantiated instance of a MovingSprite_Class. This MovingSprite_Class could be in charge of loading in the sprite and audio clip, as well as in charge of moving it according to the speed variable, changing the sprite’s color, and flipping the sprite if needed.
Classes and structs have a fair few similarities, but I prefer to think of and treat structs more as containers whereas I leave methods and other operations to classes. As we did here, we could dedicate a struct to containing information and a struct to using that information. This way the information can vary, allowing us to create a lot of variety quickly and easily while using the same system/mechanism.
As a quick note, I’m not too sure how good a practice it is, but I prefer to keep most of my structs in one place, especially if I think multiple scripts will need to make use of them. I typically do this by having a script in my project called something like ‘StructContainer’ or ‘VariableContainer’, then remove ‘: Monobehaviour’ from the class declaration (so we don’t inherit from it). With that done, mark the structs inside as public and I’d also recommend adding the ‘[System.Serializable]’ attribute, especially if you ever need to convert these to and from JSON for instance.
Assuming this new class isn’t inside a custom namespace, it should now be publicly accessible for any of your scripts as long as you include the appropriate using statement:
To wrap up, I’d highly recommend giving structs a go when you next need to set up a game system. I’ve found them to be incredibly useful for bundling information together, and beyond that they can simplify the process of setting up, say, a variety of possible enemy types or distractions by letting you define and make use of your own ‘template’ of sorts. There are also certainly times for setting up templates in a different form, most notably using ScriptableObjects, but I’ll touch on these at a later date.