One of the fundamental advantages of working with principles and architectures in our projects is that it allows us to benefit from the advantages of libraries and plugins developed specifically for those principles.
In projects where a specific design pattern is not applied, strategy changes can be made to save the situation at critical steps where adjustments need to be made.
For example, a frequently used method in the Deneme.cs script causing constant garbage allocation is a significant problem for keeping FPS stable on mobile platforms. Ideally, gc-allocation in a mobile game should be zero or close to zero (maximum ~1kb in total per frame).
Let’s assume that the event causing GC is the continuously updated scores or coin amounts of our Player in the UI. Please note that we are interacting with only one string variable here; we can perform operations with hundreds of strings while playing the game.
private void Update()
{
if(ZStringEnabled)
{
var str = ZString.Format(“Current Score: {0}”, currentScore);
_tmpText.SetText(str);
}
else
{
var str = string.Format(“Current Score: {0}”, currentScore);
_tmpText.SetText(str);
}
}
When we convert our int type score to string type in each frame, this operation will cause a new Box Allocation at the Intermediate Language level. In other words, it will cause as much garbage as the conversion of the int variable to the string type and its assignment.
There are one or several ways to save the situation in the example. The most straightforward known method is to use an intermediary structure that eliminates the allocation of the string type and stores potential results in advance to clear GC.
As seen in the values, we achieved approximately 50% performance optimization by making only one definition change. It is possible to reduce the GC Alloc value for the string to zero by advancing the steps in this method, but this example is sufficient. The total process on a computer with 32 GB of RAM has been measured as 0.1%, and this value will increase proportionally on mobile devices with 2 GB of RAM and low processing power. This is precisely why optimization has no limits.
In libraries developed based on specific principles and optimization, recovery scenarios for such frequently encountered situations have been considered in advance, and they have solutions for most basic needs.
Another feature that increases the performance of MessagePipe, which I will mention later, is their use of their developed ZString plugin. With ZString, we can handle all string type variables in the game (for example, frequently causing garbage collection, displayed in UI: instant messaging, scoreboards, market or lobby lists, etc.) at zero cost.
We know that a problem has more than one solution, and we can solve the same problem with other design patterns or custom methods without using patterns (or by overwriting the ZString plugin developed specifically for MessagePipe). However, this is only one example; in projects that adhere to principles, we have the opportunity to move on to the next step without wasting any time in many scenarios that would normally be a problem by using plugins that have already been presented as solutions by libraries developed with the same principles.
Reply by Email