📜 ⬆️ ⬇️

Optimization of the game on unity and dev story Tap Tap Builder

Every indie developer should have his own city builder in the bank, maybe that's why I decided to “design” my bike. Of course, with square wheels and a rocking chair instead of a hanger. I work alone, so there are no designers, artists, and even more modelers in the project. In addition, in general, this is my first game with three-dimensional graphics. In order not to bother learning advanced tools for creating three-dimensional models, I decided to do everything with my own hands and the means of the Unity gaming environment. There are only primitives, like cubes and cylinders, as well as the ability to paint them. Well, you had to be patient and begin to “create,” plunging into the role of the architect. Useful information for beginners indie developers can be my experience with the publisher, as well as ways to optimize the game.

image

About the game


The main feature of Tap Tap Builder is a symbiosis with a clicker, and this genre is firmly established among the general public. So, for the construction of buildings from the player will need, in addition to a certain amount of resources, pretty ponabivat fingers, zhmakaya on the screen. True, you can build a construction crane, which will build for you, but very slowly. Most buildings can be improved, and their model changes every 5 levels. Each building in the game has its own specific role.

image
')
People live in houses. Without them, the population of the city will not grow. When citizens acquire housing, they begin to look for work. For example, I can go to work in the office. Offices are the main source of loans to the city budget in the form of taxes. Someone can go to work for the plant. Plants produce resources - metal and concrete. For all buildings need electricity. To do this, have to build a power plant. In addition, in some buildings you can work yourself, while the player’s energy will be consumed, which is restored with time. For example, the player does not have enough metal. Instead of waiting for a couple of hours until it is produced at the factory, the player can go to the factory building and work there himself. And of course, the essence of the work is to 100 times click on the button that says "Work")

If the residents cannot find a job, they will have to pay unemployment benefits. However, if workers are missed, the buildings will work inefficiently. Therefore, it is important to constantly monitor the balance of jobs and the number of inhabitants.

There are quite a few buildings in the game. There are hotels and restaurants, police stations and fire stations, banks, fitness centers, stock exchanges, etc. For the construction and improvement of buildings, the player gains experience and can raise the level of the city. At the same time, he gets 1 golden key, which will be needed in the construction of special buildings. Something like RPG skill points. For example, you can build a bank, then when you exit the game all the accumulated funds will be transferred to the deposit, and the player will receive interest for the entire absence from the game. Or you can build a tax office, which increases the flow of taxes to the city budget by 10%. In addition to the main and special buildings, there are also service, unique and decorative.

Transport


There are also vehicles in the city. They are made only for beauty. If you build a city administration, limousines will start driving around the city. You can also build a showroom, then the city will begin to drive sports cars.

image

Player interaction


Among the office buildings there is a beer pub and post office. Having built them, players will be able to interact with each other, for example, exchange invites and resources. It does not need access to the network. Players will exchange bit codes, this is something like promotional codes or coupons. Each city has a unique index, which is displayed in the post office building. It must be specified as the recipient when sending the parcel. In addition, of course, you will need to choose what to send. For example, you can send 1000 units of metal, and the received code will have to be reported to a friend. At the same time, this code cannot be sent to several players, since the recipient's index is encrypted in it.

image

Similarly, promotional codes are generated, which are inserted into messages on the wall in social networks.

image

How successful this decision, time will tell. I hope that the players will appreciate the original idea.

Participation in Games Jam


The project managed to take part in Games Jam Kanobu 2016 and be in the selection of interesting projects. Alas, did not reach the final. But I managed to communicate with other developers and get useful feedback. Unfortunately, there are practically no real players at such events. But most importantly, our game publisher. They became the Russian company Herocraft. And this is awesome! In addition, there were 2 more proposals, the discussion of which ended without result.
image
So, in short, I’ll share my tips on hackathons and jam:
- look for a team. The probability of finding a team on hackathons is small. Usually, already formed teams participate, and free artists rarely look at hackathons. Try, but do not count;
- look at other projects and their results. Identify for yourself the most popular directions in the development and “borrow” good ideas);
- look for reviews about the game;
- look for a publisher;

Experience with the publisher


First of all, an agreement is drawn up, which specifies the platform for the release of the game, legal and financial issues. Before signing the contract it is worth preparing a list of questions and getting answers to them. For example:
- what improvements will be required?
- How much can the process of improvements last?
- what are the terms of the termination of the contract?
After this begins the process of finalizing the game. The publisher compiles a list of tasks to complete. I advise you to immediately decide on a convenient project management system. In my case it was github. There you can store game sources, builds and other files, as well as get tasks and bugs.
image

Regarding Tap Tap Builder, the main tasks were:
- improvement of the training system
- interface improvement
- integration of analytics tools
- increase in game performance
- content creation for game stores (icon, banner, description, screenshots, video)
- test development

I note that many subtasks had to be postponed until the release due to the complexity of their implementation. At the stage of test development, an iteration of testing takes place on the developer’s side, since all transferred tests must be at least correct.
After finalizing the game, the iteration of testing on the publisher’s side and the correction of detected bugs begins.
And now brought to the condition and the build-up build is sent to the soft launch. Softlanch is a limited publication of a game, for example, in one country and on one platform. The task of softlanch is to get feedback from real players and determine the main metrics of the game (income, retention, and others). Based on these data, a decision is made on the feasibility of a world release. In the case of a failure of softlanche, the contract is terminated, the game is returned to the developer, and he can publish it himself.

Game optimization


The first attempts to launch the game on mobile devices revealed significant performance problems. The game showed 10-15 FPS on an empty island, while the devices were far from being the weakest (Sony Z1 and Asus Transformer). Subsequent therapy allowed to increase the speed of the game several times. So, in order.

Script optimization


You should not frantically start looking for problems in the game and optimize the most likely bottlenecks. First of all, you need to run Profiler (available in the free version of Unity 5).
I immediately found problems in the scripts. The correction did not take much time; all optimization was reduced to caching information and reducing the number of calls. By the way, I recommend the design pattern Memoizer. Its essence is to memorize the result of the function for subsequent calls with identical parameters. Parameters can be not only simple types, but also structures and classes. Below is an example of using this template.
public static readonly Func<int, int, int> SumMemoized = Memoizer.Memoize<int, int, int>(Sum); private static int Sum(int a, int b) { return a + b; } 

Implementing the Memoizer Template
 public class Memoizer { public static Func<TReturn> Memoize<TReturn>(Func<TReturn> func) { object cache = null; return () => { if (cache == null) cache = func(); return (TReturn) cache; }; } public static Func<TSource, TReturn> Memoize<TSource, TReturn>(Func<TSource, TReturn> func) { var cache = new Dictionary<TSource, TReturn>(); return s => { if (!cache.ContainsKey(s)) { cache[s] = func(s); } return cache[s]; }; } public static Func<TSource1, TSource2, TReturn> Memoize<TSource1, TSource2, TReturn>(Func<TSource1, TSource2, TReturn> func) { var cache = new Dictionary<string, TReturn>(); return (s1, s2) => { var key = s1.GetHashCode() + "." + s2.GetHashCode(); if (!cache.ContainsKey(key)) { cache[key] = func(s1, s2); } return cache[key]; }; } } 

Optimization of three-dimensional models


After the problem with the scripts has been solved, it's time to do rendering (rendering). A significant impact on performance was made by the fact that building models were made from primitives that had different materials (and colors). Statistics showed about 600 draw call (after autobatching) and 100,000 triangles. For comparison - currently for a spherical game in vacuum it is recommended to have up to 100 draw call and up to 30.000 triangles.

image

The first solution is to reduce the number of surfaces. I had to import the asset to edit the meshes. Many buildings contained cylinders, and the standard cylinder has 20 faces and 80 triangles. Simplification of the geometry of the cylinders to 12 faces gave a tangible effect to the detriment of the small angularity of buildings.
image
The next step is to remove invisible faces from the primitives. As a result, a significant reduction in the total number of triangles (about 20%) did not bring any increase in FPS. Probably, the engine and so does not spend resources on rendering invisible geometry, even if it is within sight of the camera. The result is a useless step.

Batching


The next step is an attempt to use static batching. Briefly tell about the batching, for those who do not know. Butching is the grouping of meshes (mesh) into 1 common mesh before a draw call. It just so happens that the video card is easier to draw 1 object at once, than in parts for several calls. At the same time there are several nuances. Merging is possible only for meshes that use the same material. Secondly, the total number of vertices in general should not exceed 900. And third, changing the transform (position, rotation and scale) of child objects is impossible. For example, the “sbatchenoy” car model will not spin the wheels. Butching is static and dynamic. Dynamic batching works at runtime and does not require any action from the developer. The result of the dynamic batting can be seen in the Statistics window.

image

Static batching can be implemented in two ways - by ticking Static for an object on the stage or a prefab. These can be static game objects, such as landscape elements, vegetation, and buildings. The second way is to use the StaticBatchingUtility at runtime.

It was quite logical to do static batching for buildings, which I did. As a result, the game began to work even slower! As it turned out, forced static batching breaks the work of dynamic batching, which works more efficiently and groups meshes from different logical objects, for example, belonging to different buildings. In addition, automatically grouped objects can move relative to each other (the grouping is canceled). The result - the use of static batting can be useful only with a deep understanding of the logic of its work.

Shadow Optimization


The following observation - turning off dynamic shadows reduces the number of triangles by exactly 2 times, which gave an FPS increase of about 20%. Changing the quality of the shadows of the visible effect is not given. In this situation, there is a simple standard solution - replacing shadows with sprites. Such shadows are often called static. Immediately the question arises - how to get the shadows of objects, because not to draw them manually? The simplest solution is to use blurred circles. This would be suitable for shadows of characters in a simple runner or shooter. This decision did not suit me - the shadows should repeat the geometry of buildings. Well, I had to write a script for dumping shadows. The operation algorithm is simple - the script takes turns creating buildings (from prefab) and takes a screenshot of the building with a shadow, saving it to disk. Then the second script performs elementary processing of the received images, filling the shadow with black color and deleting the background (by color). Alas, I did not find ready-made solutions, share your experience in the comments.

image

The result is an increase in speed by 20% with the appearance of minor artifacts (when applying and layering shadows). By the way, sprites with shadows need to install a Packing Tag, for example, Shadow. Then Unity will create an atlas for them (atlas), and the rendering of ALL shadows will be done in 1 draw call. And one more note - some devices may have problems with the display of dynamic shadows, so replacing them with static shadows will avoid problems.

Further optimization of three-dimensional models


Unfortunately, the result of the optimization was unsatisfactory - the game showed 20-25 FPS on a powerful device. I decided to write another script for baking models. The bottom line is to generate a new mesh and apply a texture to it for coloring buildings. The texture is a simple 8x8 color palette that can automatically fill when new materials (colors) appear. At the same time it is necessary to form the correct UV-mapping. At the Asset Store there are plugins for baking objects, but they did not know how to generate texture by the color of materials. I will not dwell on the details of the implementation, because I understand that my situation is quite specific. Although, on the other hand, this method may find application in the currently popular voxel graph. It is much more convenient to make prototypes of models in Unity than to study modeling. Unless of course, you have a team, no modeler, like mine. I had no one at all).

image

The end result exceeded all expectations - the game speed increased significantly. The game shows 50-60 FPS on a huge city. Further optimization is not required.

Conclusion


I apologize for the fact that the article was very large. After all, I wanted to tell about the game and share my experience. And finally, my advice - make cool prototypes and do not waste energy on optimizing the game until the working version.
I will be glad to hear your optimization tips in the comments, as well as ready to answer questions!

Link to the game on Google Play

Source: https://habr.com/ru/post/282391/


All Articles