Recently I was tasked with calculating all the possible legal moves of a selected chess piece and visualize them in Unity.
My first thought was to look around the internet to see how different people are actually implementing this to get some references. Among them I saw a lot of the projects have a similar Object-Oriented structure.
A script/class is created for each piece type that contains an array of vectors representing legal directional moves of the specific piece, and the logic to highlight those moves.
By this method we have 6 scripts - King, Rook, Bishop, Knight, Queen and Pawn which will be assigned to their respective Piece object in the Scene. See the Diagram Below.
To summarize, for Player 1 we would have had 16 instantiated scripts with duplicate static data co-existing with the logic in the memory.
This method did not sit well with my brain and thought process. As a result, I started thinking of a different way to structure and implement this mechanic that would save me some time and energy.
Takes data from a single place - ScriptableObject
Process it in a single script
Script is attached to a single GameObject
My first thought was to separate the data and logic. To achieve this I created a Dictionary(used to store data in key : value pairs) which stores all the arrays containing legal moves of all piece types with their respective names as the key to access them.
This Dictionary (MoveSets) is stored in a ScriptableObject called MovesData at the project level.
ScriptableObjects are data containers independent of a GameObject. Scripts who want to access data from a ScriptableObject have to just reference it. These are stored at the project level.
This acts as a database which can be accessed by any script and hence makes this scalable and modular.
I made custom tags for each piece type and assigned to each object. These will serve as Keys to access data.
I made a single script GenerateMoves which calls a function ShowMoves() when a piece is detected on mouse click and passes its tag. Since most of the logic of highlighting cells is the same, there was no need to create separate classes for each Piece type.
The function then gets the respective Piece's legal moves from the Dictionary MoveSets with the help of the Tag passed acting as the key.
ScriptableObject MovesData accessed by reference.
The function then traverses through the Vectors and checks if the move can be made or not.
Iterations are determined by switch cases.
This design is highly scalable and modular
If a new Piece type has to be added, one only has to add another move set to the Dictionary and assign the tag matching the key to the object.
The same data can be accessed by the opponent without extra cost. Good for online multiplayer.
Separation of data from logic promotes modularity. Easier to make changes without causing unintended side effects.
Memory friendly - Prevents data duplication and unnecessary instantiation.
Thank you for reading through my post. I would greatly appreciate any kind of feedback or suggestion. I would love to know your take on this problem and how you would go about it.