How ECS, C # Job System and SRP change the approach to architecture

    We in the company have been working with Unity for a long time and could not help but invite their guys to Pixonic DevGAMM Talks, which was in September. Field Engineer Valentin Simonov told how to plan the architecture of games, taking into account the advantages of new technologies. Unity has been working on them for several years to achieve a previously unattainable level of performance. You can listen to the performance on YouTube, and read the transcript with the slides right under the cut.

    What if I say that you can increase the performance of your game 10 times? In fact, this is not entirely true, but in every joke there is some truth. I want to talk about what we are working on now, what will be the future of Unity and what you can use right now.

    Unity makes completely different games. Here are examples that I play myself. They use different features and they need different performance, a different approach to development.

    And we are working on a project called Performance by Default. These are a few special features that, if used properly, will achieve a significant performance boost. In some tasks, we measured x10 and even x11. Especially in the problems of simulation of a large number of objects that interact with each other.

    But when we talk about Performance by Default, we mean that you will have to change the approach to development, greatly change the approach to the architecture of games. And, in fact, not everyone needs it.

    A popular question: “What are you doing in your ECS? Will you remove all GameObjects, remove all Transforms, hierarchy and components? ". No, we'll leave it all. You can work with Unity exactly the same way as now, but if you want more performance, then you need to know about the technologies that I want to talk about in brief.

    And I want to mention another technology called Scriptable Render Pipelines (SRP) - it allows you to write a render-pipeline more efficiently for your game. Probably, you saw the demo that we showed on one of Unite. Here on the PC in real time a huge number of units is simulated, something around 60 thousand (reaches 100 thousand and starts to slow down a little):

    And the new features that I want to talk about are: Entity Component System (ECS), C # Job System, our new Burst supercompiler and Scriptable Render Pipelines (SRP).

    I repeat: you choose, you want to go ahead with us, learn new technologies or you are OK to develop games that are already making good money and are simply being made.

    To understand what we are trying to solve, it is important to understand the state of iron in 2018.

    Notice how the performance and the number of CPU cores grow. At some point, Single-thread Performance even went down. That is, we now have a lot of cores, but their performance is growing not so fast. Therefore, we would like to use the power of all the nuclei.

    My phone has 8 cores: 4 strong and 4 weak. And a modern phone can work as fast as a modern computer (but not for very long due to overheating). You also need to understand that the increase in performance is not only the use of all cores, but also the optimization of single-core performance.

    And the last picture, which we always cite as an example of how the performance of processes goes up, and the speed of access to memory does not increase so much:

    It can be seen that memory access is extremely slow. Processor manufacturers are doing a lot to level this difference - they add caches, CPUs are engaged in speculative computing, trying to predict what code will be executed next. And if you do not think about it when you make your game (or when we make the engine for you), then we cannot take full advantage of modern processors.

    Probably many of you are looking at a similar picture for hours in Unity:

    Here you can see that there is multithreading, but the rest of the cores and threads are mostly not busy. Something is being done, but I would like to take them completely.

    Now rendering with us, this is such a black box. You have a choice: Forward or Deferred, plus different settings for materials, shaders, Command Buffers and so on. You can make a beautiful picture, but many algorithms are extremely difficult to implement.

    And we all know about the architecture in Unity: components, GameObjects, Transform hierarchy, all code, all data in MonoBehaviour, and each component processes its data.

    But there are problems with the current state of affairs. Sooner or later you come across this and understand how to do it and not to do it. The hierarchy of objects in itself has a certain overhead, and some entities do not have to be GameObjects at all. And if you have a large number of components and updates for them, then everything becomes much slower. I once wrote this articlewhich is still relevant if you want to learn how not to do it.

    And the most important thing in the context of processors is that all components, all data are scattered in memory, which breaks the use of the processor cache.

    Now I want to quickly go through the new features.

    I will not focus much on what ECS is and how it works. The point is that we have Entity, which are just IDs of certain entities in the game - they store data in the form of components, i.e. data only, no code. And the systems process Entity with certain components and somehow change this data.

    Why do we make our ECS and how will it be better than competitors? There are a few points. The first is not quite official, but we think that we would do the engine like this now. It is clear that we do not want to get rid of GameObjects, the current components of Unity, completely throw everything out and put ECS. But we want to move towards a better engine.

    We do the calculation for high performance. Not so long ago, Mike Acton joined us (if you are in C ++ development, then you know that he is one of the evangelists of Data-Oriented Programming). And we want to make the whole system work as fast as possible - faster than C ++.

    We are also thinking about how to integrate different things natively in ECS. Some time ago we announced that we are doing new networking and it is also based on ECS - it will be possible to make a multiplayer game on ECS and share the code between the client and the server.

    We are working on debugging tools in Unity. Those. for now, ECS exists as if separate from GameObjects and components, and this is very inconvenient. We want to simplify everything.

    Now there is a DebugView, which looks like this:

    Here you can look at what Entity you have, what systems take how much time to process, which systems work with which components and for each component you can see in the inspector, what data each Entity has in the components (I note that the API often changes and many tutorials may have become outdated).

    Also, if you heard about our new development Unity for Small Things (this is a very small runtime that allows you to make games for instant messengers) - there, too, everything is built on ECS.

    Recently, the boom of development and transition to ECS is a very popular technology and everyone needs to know it.

    We have a conference for programmers, so it’s hard to do without a slide with a code. There is a lot of code there, so it’s hard to pull out some intelligible piece so that something is clear.

    In fact, I took one system from the example that works with the C # Job System (which we will discuss later), and we do a lot to reduce the amount of code, add syntax sugar.

    There is a system that works with RotationData components, and it also needs GameObject transforms, which are represented by the special TransformAccessArray thing. And each update of the system we create a Job, run this Job, it will be updated somewhere, maybe divided into several groups and executed on different threads.

    How to use in the project? Just as in other ECS implementations, you need to understand what to think will have to be completely different (unlike GameObjects and Transforms). And get used to this idea. It is clear that you need to start from the very start of the project, because I often get questions like “we made the game and want to switch to ECS - how?”. In the finished game this is very difficult to do.

    You need to think about interacting with Unity, since ECS lives separately, in its own small world. We provide some interaction with GameObjects and Transforms, but physics, rendering, etc., is becoming more and more difficult. And while you need to reconcile with the fact that much of the familiar interface will be unavailable, but we are also working on this.

    And immediately you need to think that you will write systems in the Job System, which is much more efficient.

    A few words about the Job System. We want to make a very simple way to write multi-threaded code. At the same time, write in C #, check everything for you, not give the opportunity to make mistakes or show why, where and how you made them. We limit the language you can use in jobs, and call this subset C # High Performance C #. You have no references in the Job code, there are no lines, all the data needs to be copied - you cannot use a large number of language features, thus, it becomes much more difficult to shoot yourself in the leg with multi-threading.

    We also present very fast collections and integration with ECS. This ECS and Job System structure allows for very fast code execution.

    In this case, we not only give you the opportunity to use these technologies - we ourselves work with these systems and create new APIs so that they can be used in Jobs.

    We made Async Raycasts for physics, with which you can say “I want 600 rakests, do me sometime, please”. We are working to make it possible, using these technologies, to expand current systems, for example, animation through the Playbles API. And we are thinking about making new systems in Unity, which will not be closed in C ++, and whose code will be in C # and available to you.

    If you take the code Job'a pretty simple. A job is a structure in which there is a Execute method, where we do some work by running this Job. Accordingly, our internal Scheduler will sometime understand where it is better to start it, will resolve all dependences. Here we get a JobHandle, which we can use as a dependency for some other Job'ov.

    How to use in the project? It is good if you use jobs from the very beginning, but here it is not necessary. If you have some kind of Performance critical system, say, simulation, pathfinding, networking, or something else - you can figure out how to optimize it with this tool.

    But for this you need to take a few big steps, to understand how to properly store data. ECS just allows you to properly store data, because we separate data from code and our implementation ECS stores component data linearly in memory, and, running through these components with a system, you use all the capabilities of the processor, everything is stored in the cache and etc. We try to do it very quickly.

    Further you break this work into parallel tasks, write a Job-code and start. And you (probably) everything works. Of course, you need to test and, most importantly, test on the target platform, depending on the number of cores, etc. But the use of the Job System and ECS also, as I have already said, greatly influences how you plan the architecture of the game.

    Then everything is much easier. Burst Compiler is our unique technology, a special compiler of this C # subset (High Performance C #) into the machine code of the current platform you are publishing to your project.

    The guys did some kind of magic that probably no one except them understands, but this thing speeds up the Job code 10 times, which is super cool. And the coolest thing is that it doesn’t require any action from you - if you have a job code, you just add the [BurstCompile] attribute, Burst compiles your code, and you get “free” performance. This is our new technology and you can try it now.

    And the last thing I want to briefly mention is the Scriptable Render Pipeline (SRP), on which we have been working for a long time and which is designed to give you the opportunity to write very customizable rendering for your particular game.

    Render Pipeline is some algorithm that Culling does (which objects will be drawn), Rendering and Post-processing. Now we have blackbox, which is Forward or Deferred - they are so good, we get very cool graphics on mobile phones, on PCs, on consoles. But they have a lot of restrictions, because they can not be expanded. Using this new feature, SRP, you can write your Pipeline, you can remove something from there, add, do whatever you want.

    We are currently working on two examples of pipelines. One LWRP, which we target on mobile phones and weak devices, and HDRP, which we target on the PC, consoles and which are very well-known people in the industry. Before that, they were doing AAA games. Surely, you saw our demo of Book of the Dead.

    Here we used HDRP to show the full power of this technology.

    To use this, you will also need to take a fairly large number of heroic steps, because with the new Pipeline there is almost nothing compatible with what we have now. Those. if you upgrade from Legacy, then we give a utility that upgrades most of the materials for you, but you will need to rewrite your shaders, i.e. textures will most likely look different.

    Very cool if you can start from scratch and experiment with your Pipeline. If you want to do something on your Pipeline, please contact us.

    Again, understand what you need, because now you have more opportunities to do something, but you will need people who can do it or you will have to learn how to do it.

    In my opinion, this is cool, because those who go ahead with us with these new technologies will be more in demand in the market. That's all, I hope someone will go and look at these technologies, make beautiful, cool games.

    Questions from the audience

    - When can I take ECS and develop it?

    - You can use ECS, the problem is that in its current form it is more targeted to people who are focused on performance, i.e. some kind of AAA project. And the task of Unity is to make Performance by Default accessible to everyone. Therefore, we need a certain system, an add-on to ECS, which would allow us to use ECS as easily as we use MonoBehaviour. While there is no such add-in, I do not think that ECS will be released in a full release. And it turns out that we have made a feature that will be used by 1% of our users. This is not a Unity task. I know people who already use ECS in production, just keep in mind that this feature is still deep in development and now we are deciding how to make the interface as convenient as possible. And the next task (no less difficult) is how to make some kind of API, which lives on top of this ECS and will allow you to use it with the same ease as MonoBehaviour. Those. answer to the question "when exactly" yet.

    - ECS and the rest of the points are focused on taking some basic GameObject and making 150 thousand of its clones and managing them. And what if I have few objects, but they have different entities?

    - You can, in principle, do nothing, this technology does not oblige you to use it. If you can get a performance boost using these technologies, you should use them. If this is irrelevant for you, then you continue to use Unity as is. So please do not panic.

    - We have a client on Unity, a server on .NET, tried the server on Unity, nothing comes out. But at the same time, I want the technologies that are in Unity, and use on the server too.

    - We are working on it and we understand that now we can not provide an effective server solution. We bought the company Multiplay some time ago in order to make high-quality hosting for Unity-games. We do networking separately and separately we are engaged in optimizing the engine so that more things can be thrown out of it. Accordingly, when it all comes together, we will have an excellent multiplayer solution.

    More reports from Pixonic DevGAMM Talks

    Also popular now: