Building a Board Game in Unity

Basic Dice Mechanics
When I first started learning how to code C# in Unity I gave myself a simple task to prove I understood the basic underlying concepts I’d been absorbing: create a basic dice roll mechanic. As beginners tend to do, I thoroughly overthought the program. I created a Dice class and populated it with separate int variables for everything from a coin flip (d2) through every value of what some may derisively call “Dungeons & Dragons dice,” then similarly created methods for each to calculate their random values.
And when I attached the script to my player, the methods didn’t really work as I envisioned, I couldn’t figure out how to retrieve the result even if they had, and I certainly didn’t know how to implement it in a game-relevant way.
Fast forward [loud cough] years, and I can say my initial assumption was correct, though. The task is actually very simple:
In five simple lines you can abstract the Random.Range()* function out of your code and emulate any die roll value in a much more efficient and human-friendly way. Here’s how it breaks down:
The method is declared as public, because the intention is that it’s going to be called from any number of different systems that will need any denomination of die roll and will therefore live in some kind of manager class that communicates with other scripts.
Next is the int return type. This is one of the big pieces I was missing as that neophyte coder at the beginning of the story, and the reason I couldn’t extract the result of my calculations. The simple explanation is that with this return type declaration, this method will produce a piece of data (an int, in this case), that we can then use however we need.
For more on this, I’ve written about return-type methods before.
Remember all those redundant variables I thought I needed? The next part of the declaration renders them all irrelevant. After naming our method, inside the parentheses we tell it that whichever script is invoking it, they need to pass in an int parameter (dSides is just an arbitrary variable name, but in this house we give our variables plain-language names).
Think of it like a typical table-top RPG: each player has their own bag of dice that they’re responsible for rolling, the mechanics of the roll (physics and chance) are agnostic to which die they cast, just like our DieRoll() method. The script calling the method will be responsible for determining which “die” is “rolled.”
Next, we do our calculation, storing it in the rollResult variable, then return that variable as data and close the method.
Multi-Die Rolls
Going back to the tabletop RPG analogy, what about when the player’s weapon has a damage type that calls for multiple die rolls? Or rolling two movement dice, like in Monopoly? Instead of calling the DieRoll() method multiple times and adding the results together, we can simplify it even more using the concept of polymorphism.
That’s a $20 word for a simple idea: in this case, all we need is a copy of the original DieRoll() method with a new parameter:
This overload of the DieRoll() method will take the same dSides parameter, then adds a count called rolls to iterate how many times that die is rolled. The simple for loop adds the results of each roll together to get the total we need.
You can add as many overloads as you need to accommodate rolls that take in any number of rolls for any combination of n-sided dice your game requires.
Strip it Down
Six hundred twenty-eight words later, I have a confession to make: for the game I’m building out, we’ll only ever need to roll one six-sided die once at a time. If there’s any major difference between me now and me at the beginning of the story, it’s figuring out when to keep it simple:
With the first basic mechanic solved, next we’ll how to take the result of our roll and turn it into player movement.

*We need to add +1 to the end of the range because the int type of Random.Range() is max exclusive, meaning it excludes the highest value. This is convenient for cycling through indices of arrays and Lists to prevent out of range exception errors, as we’ll discuss later.