Unity from the perspective of the artist in the development of cross-platform games
After many years of working with Flash and game engines using it as a shell, where everything needs to be created manually, and the possibilities are limited to a couple of points, the news about working with Unity made me euphoric.
“Working in Unity is so pleasant and convenient: there are many opportunities for self-realization,” they told me, but it turned out to be not so simple. This article will not be sung laudatory odes Unity. This article is about the harsh realities, limitations, and difficulties that our small indie development team faced when creating their first, but rather large, game Death Point.
')
The start was promising. In just one month, we collected a prototype in which there was a small level, a character and a pair of security guards who were engaged in their outstanding activities.
The first problems arose at that moment when I finally decided to try a lighting system on my teeth. In view of the fact that we wanted to achieve cross-platform for the game, it was crucial to maintain the same high level of graphics on any device. It was here that I first wallowed in the weak, as it later became clear, Unity documentation.
Lighting
Our forces were extremely limited and I chose the tile system. Flexible, allowing to achieve good visual diversity, limited means. Looking at my faded level, I with tears in my eyes studied the documentation on Unity in search of the answer “setting up and operating the lighting system”. The documentation turned out to be rather superficial and did not give a complete understanding of the work of the system. I was saved by the documentation of the Unreal Engine, which reveals many aspects of how it works in the game engine and gives many answers to the “how to do” questions. Another couple of three good articles and I was ready to create.
The first blow was the incredible difference between what Unity displays in the editor with real-time render and bake. The beautiful shadows after baking turned to porridge, the light sources clogged each other, their brightness and color changed dramatically.
In fact, the whole lighting setup has been reduced to remembering how a particular light source looks with different configurations. Set the option - turned on the render. Did not like the result - change the settings and render again.
Then, the lack of HDR in variations for mobile devices. Everywhere there are ticks to enable it, but the result was only an eerie jumble of colors from a light source on objects, Unity simply does not understand how to save a light-map in HDR. As a result, the texture is lightened to the level of albedo, and a “rainbow” gradient appears at the edges of the illuminated area.
Earliest Baked Light Test
After a brief war, in which I certainly lost, it was decided to take a detour. In order to achieve a flare effect, I simply began to redo all the materials so that the albedo maps were light, and even small values ​​in the intensity of the light source gave a flare effect.
After a lot of manipulations - a beautiful gradient with a pattern
In the same picture you can see that in front of the lamp there is a 3d object with a transparent texture that acts as a mask. That's because the developers did not add the ability to set a texture mask for the baked light source (mask of the light spot).
A separate item can be mentioned directional-lightmap - an excellent technical solution, but because of the mobile orientation, we did not use it. Lightmaps themselves weigh a good deal, and directional-lightmap doubles this value. We could not sacrifice so many resources, since the game was supposed to work well on mobile devices. The reason is that the entire directional-lightmap effect is only visible when the light source enters the camera. And there are very few such moments in the top-down game.
Size matters
The next unpleasant moment was the caching system, which works with errors, which greatly affects the final result. If you bake the light with pre-cleaning the previous result, then you get the same thing. But if you bake over the existing result, then each subsequent one differs from the previous one, albeit slightly, but after several iterations the difference was enormous. No, this is not something that would be a bad result, but extremely unpredictable.
When it came time to understand what we were capable of, a rather impressive level was put together. And here again blow from a belt from developers of Unity - errors that it is impossible to bake lightmap fall to the console, and level becomes covered with black strips. Level too high and lighting settings too high. It's a pity.
Here it is, that level, with good illumination, tuned with reflection samples, light-probe for illumination of dynamic objects and with partially implemented gameplay. Looks good, plays great. A glance falls on the number of drawcalls - failure, total failure ... there are about two thousand.
Where do these numbers come from? There are a hundred unique objects on the stage, and the clones have to be bathed by the internal system. A week of searches was not crowned with success, a few guesses and assumptions, a ton of tests and tinkering in the settings - all in vain. At some point, Unity completely refused to merge the same objects when rendering, rendering them one by one.
Our game designer turned out to be an intelligent guy and a good programmer. In just a few weeks, he wrote his optimization system, which grouped and merged meshes, created atlases from all the objects used in the game, and a whole bunch of different things I don’t understand =). As a result, we achieved a quantity of drawcalls acceptable for a mobile application. With a maximum detail of the scene there were no more than 250. Still a lot, but a good phone copes with a bang, giving those very cherished 60 FPS.
After entering the optimization system, the number of drawcalls stably keeps around 100.
Own shader
And yet, there was something wrong with the picture. The result was far from expected and, especially, desired. I did not immediately see that the models look too different in the 3D-coat, where I make the textures, and Unity, believing that the whole thing is surrounded by this object. Despite the tremendous work done by Unity developers to optimize the standard shader, tests on the devices showed that everything is not very good. Yes, quickly, but not as I would like. Yes, PBR (Physically based rendering), but it looks weird. The incorrect work of the reflection sphere on mobile devices using graphics API 2.0 has become one of the main reasons for writing its own shader. We didn’t want to switch to 3.0 due to a performance failure.
I did not want to use spherical reflections; it looks weird and ugly, the character moves and the reflections move with it. When the camera is looking at the ground in the game, the options for decorating the picture are few and the reflections on the surfaces of objects play a really important role.
Generally PBR in Unity is the story of PC games, in which it feels good in realtime coverage. In the case of baked lighting and the lack of directional lightmaps, PBR becomes a pile of garbage that does not understand how to behave. Yes, someone can say "Why it was impossible to simply use a mobile shader in which the cubemap is sewn up?". The answer is simple: we have a lot of reflective surfaces in enclosed spaces. Reflections do not just shine beautifully, they emphasize the shape and give a better understanding and understanding of the properties of the material from which the object was created, they set the correct atmosphere for the room where the character is. As a bonus, you can see what you should not see: the facades of buildings (which we do not display in the main camera, so that they would not interfere with the gameplay), the ceilings of the rooms, and just various accessories and signs that are inaccessible to of this camera angle field. Everything shines, glitters and reflects, creating a whole atmosphere and enlivening this digital world.
No reflections
With reflections
Fake reflections can give an acceptable result, everything will shine just the same, but the player is hard to fool, he may not understand, but he will feel that something is wrong here! In the end, all the illusion, which so long sought, will be destroyed.
When writing our own shader, we, initially, simply copied the decision of the unit - we broke the shader into 2 parts: “metallic” and “speculator”. I did not immediately realize that this is the part where everything is very bad. This solution does not allow creating complex objects combining metallic and glossy surfaces. One thing to choose from.
In sum, with our optimization system that collected all the textures in several atlases and used one shader for everything, the picture looked weird. Everything either gave off metallic shades, or, on the contrary, seemed like a simple gloss. Approximately the way it was in DOOM 3, when all surfaces glittered mercilessly.
In Unity there is an amazing opportunity to create composite shaders, which, depending on the input parameters, throw out unused blocks. Those. if there are 7 input parameters in the shader, but only 3 are used, then at compilation it will create a shader version in which there will be only 3 parameters.
Two versions of the shader were created, one debug, which operated with all possible texture maps separately, and final, operating with four assembled texture atlases.
As a result, we got a decent amount of input to the debug version of the shader:
1. Choose between transparency / opacity 2. disabling the Normal Map (its absence on one object gives a small performance boost, but disabling in large quantities gives a noticeable result). In our case, this makes sense, since the camera is located far enough and it is not always wise to use it, often adding ambient occlusion to albedo showed noticeably better results. Next come various texture maps, which I can immediately in the shader multiply by some color or value. 3. Albedo 4. Specular 5. Roughness 6. AO 7. Emission 8. Metal 9. Normal map
During the compilation process, all this variety fits into 4 textures.
What makes life easier for me as an artist - I have a flexible tool that allows me to get any desired result and at the same time is quite easy in terms of performance, especially if I do not use all the possibilities. Thanks to all of the above, I could not afford to worry about the size of the textures and, if necessary, multiply the color values ​​by textures, which accelerated my work, because I did not have to go into the graphics editor and save everything again.
Another advantage was the system of calculating the size of the 3D model in the world, which allowed me not to think about the size of textures. There was no need to suffer and choose between low-quality texture at 64px or too detailed at 128px. The system simply compresses the texture to the required size and packs it into an atlas. As a result, for the player, everything has the same high-quality details.
Character vision zones. Fog of war
I will tell about one of the most ingenious and simple solutions that we used in our project. The fog of war is realized through point-light, located in the character and rendered as a separate camera with the simplest possible shader, which takes into account only the lighting. The result is a character visibility buffer used for the post-war fog process and as a mask in other shaders. For example, in sight of the guards.
Conclusion
As a result, we have created a powerful and flexible tool that allows us to get both the most beautiful graphics on a PC, and its slightly lightweight, but still looking great version, on mobile devices.
There is an idea to unload the finished level back into the 3D editor and bake the light there. This will give a huge increase in the speed of preparation of the scene, and in the quality of the result. Believe me, it will be amazing. Soft and hard shadows, lights, high-quality gradients. Do you think only FrostBite can show all the possibilities of a beautiful render on the verge of your hardware? Our team can show you how really beautiful games should look on all devices, with all the same ridiculous hardware specifications. But, no matter how many ideas, time is needed for their implementation. Entering STEAM can give us the opportunity to realize all our ambitions, but for this we need your help!