Mar 9
For Witch's Garden (WG) I have challenged myself to try to make the code for our systems as robust and portable as possible within the short scope of development time. I am quite happy with how the back-end of how our research system turned out.
At the time of implementation the goal of the system was to support a pseudo tech-tree that the player can spec into to earn upgrades. The upgrades would range across the board and touch multiple other systems in the game. This was an important point when architecting the code. I knew if I wanted this system to be portable, that meant isolating implementations specific to WG into contained areas.
So the ResearchSystem takes in a ResearchChapterTemplate which consist of a list of ResearchItemTemplate's .
A ResearchItemTemplate is an abstract class that exposes serialized fields for the data all research items will share.(Name, Description, Image)
I originally made an enum for the type which violates the Open-Closed principle, but I went with it because I thought further down the line when unpacking these items, there would be a slight performance increase of checking an enum before a type cast. (We'll get there in a bit).
I then made concrete implementations for each type of research item we needed
Next up we have the ResearchPayloadHandler which is the other part of this system concerned with concrete implementations. The payload handler is binds itself to the research system, and gets a callback when a research has been progressed to 100%. It's job is to figure out how to execute the reward. Because of this our payload handler is the other section of the code that ends up knowing about the specific systems of the game, and handles carrying out those type casts when being passed the abstract base class (As mentioned earlier with a pre-check on the enum).
private void ResearchGainedProgress(UnlockedProgressableResearchItem item)
{
if (item.Progress != 100)
return;
ExecuteReward(item);
}
Taking a look again at our pseudo UML , you can see we reduced the concrete implementations to 2 areas of the system. The rest of the system is reusable. Anytime you need a new research, you extend the base class, and add another condition to the payload handlers switch statement.
After thinking about the enum/explicit cast checking situation , I wrote some tests that determined there is actually no clear performance benefit from this. Since it violates Open-Closed and decreases readability, I have removed this, leading to a much nicer looking switch statement as well.
Results after first pass UI
Thanks for reading our blog and be sure to check back in the future for more!
Comments