📜 ⬆️ ⬇️

Unity, ECS and all-all-all


How many have been already manuals "How to make a game on Unity in 3 hours", "Making Counter-Strike in the evening", etc.? Low entry threshold is undoubtedly the main plus and minus of Unity. Indeed, it is possible to distribute “assets”, add a few simple “scripts”, wrap with blue electrical tape and it will even work somehow. But when the project is cluttered with game mechanics, a complex logic of behavior, the problems with this approach increase like a snowball. For the introduction of new mechanics, rewriting of the code in many places, constant checking and reworking of prefabs due to beaten references to logic components, not to mention optimization and testing of all this, is required. Of course, the architecture can be thought out initially, but in practice this is always an unattainable goal - the design document changes quite often, some parts are thrown away, completely new ones are added and not connected with the old logic of behavior. Components in Unity is a step in the right direction in the form of code decomposition into isolated blocks, but the implementation features do not allow to achieve the necessary flexibility and, most importantly, performance. Developers come up with their own frameworks and bicycles, but most often stop at ECS (Entity Component System). ECS is one of the solutions that continues the idea of ​​the Unity component model, but gives it even more flexibility and greatly simplifies refactoring and further expanding the application with new functionality without major changes in the current code.


What is ECS


ECS is the Entity Component System design pattern (Entity Component System, not to be confused with Elastic Cloud Storage :). If in a very simple way, that is, “ Entities ” (Entity) are container objects that do not have properties, but act as repositories for “Components”. “ Components ” are data blocks that define the various properties of any game objects or events. All this data, grouped in containers, is processed by logic that exists exclusively in the form of “ Systems ” - “pure” classes with certain methods to perform. This pattern is independent of any “engine” and can be implemented in many ways. All “entities”, “systems” and “components” should be stored somewhere and initialized in some way - all of these are implementation features of each ECS solution for a specific “engine”.


Wait, you say, but that’s true of Unity! Indeed, in Unity, “ Entity ” is a GameObject , and “ Component ” and “ System ” are MonoBehaviour's heirs. But this is the main difference between the Unity component system and ECS - the logic in ECS must be separated from the data . This allows you to change the logic very flexibly (even delete / add it) without breaking the data. Another bonus is that the data is processed by the “stream” in each system and regardless of the implementation in the “engine”, in the case of MonoBehaviour there is quite a lot of interaction with the “Native” part, which eats up part of the performance. You can read about the features of the internal method of calling methods from the heirs of MonoBehaviour in the official Unity blog: 10,000 Update () calls


ECS Example


The task of the designer: “it is necessary to make the player move and load the next level, when he reaches the point X”.
We divide the task into several subtasks, one by one into the “system”:



Define the components:



And this is how it all works:



UPD: josinSbazin made the implementation of this test task.


It looks like an excessive complication of the code compared to one “MonoBehaviour” class in a dozen lines, but initially:




ECS Features


Based on the example above, you can deduce the main features of ECS with respect to the Unity component model.


pros



Minuses



For many who have worked with Unity for a long time and have never used ECS, it will be difficult at first to get used to this approach. But soon, you start “thinking” with components / systems and everything is assembled faster and easier than with strongly connected components based on “MonoBehaviour”.


Embedded ECS Solution in Unity


Now even the Unity developers themselves realized that it was time to change something in their component system in order to improve application performance. Somewhere a year ago it was announced that the development of its own ECS and C # Job system is underway. And now, in the 2018.1 version, we can already roughly imagine what it will be in the future, even in the Preview status .



With regular Unity ECS, nothing is clear yet. Developers do not write anywhere that it is suitable only for a limited range of tasks, but when questions arise as a result of rewriting from other ECS solutions, they respond in the style of “you misuse ECS”. Those. in fact, this is not a “multipurpose” solution, which is rather strange. There was no release, they can still change several times, there are problems with the transfer of reference types (for example, string), so I can not recommend doing something big on a regular ECS in its current state.


Alternative ECS Solutions for Unity


The ECS pattern was not invented yesterday, and on https://github.com you can find many of its implementations, including versions for Unity. Relatively fresh and updated:



I dealt with only the first two options.


Entitas is the most popular and supported by a large community solution (because it was the first). It is quite fast, there is integration with the Unity-editor for visualizing ECS ​​objects, there is code generation for creating wrappers with a convenient api on top of custom components. Over the past year, the code generator has separated into an independent project and has become paid, so this is rather a minus. Another rather significant disadvantage (especially for mobile platforms) is that memory is allocated for all possible components on each entity, which is not very good. But in general, it is good, well documented and ready for use on real projects. Size: 0.5mb + 3mb support editor.
There are a lot of examples using Entitas , but there is also a project for a long time. From examples with source codes it is possible to look at Match 1 .
Entitas’s overall performance is estimated like this:


With LeoECS, I know better, because I'm doing a new game on it. It is compact, does not contain private code in the form of external assemblies, supports assembly definitions from Unity 2017, is more optimized for memory usage, almost zero GC (only on the primary set of pools), no dependencies, C # v3.5 with optional inline support for FW4.6. From the nice things: DI through markup attributes, integration with the Unity-editor for visualization of ECS-objects and ready binding for uGUI events. Size: 18kb + 16kb editor support.
As a ready-made example with the source code you can see the classic game "Snake" .
Speed ​​comparison of Entitas and LeoECS : the results are quite close with a slight margin on both sides.


Conclusion


I am not an expert in this matter (only recently I started using Unity in conjunction with ECS), so I decided to share my observations and thoughts first of all with those who "collect" games on Unity from assets with a bunch of scripts on each. Yes it works. Himself such was. But if you are not doing a prototype or any one-time game without the need for its support and further development, then think 10 times - then you will have to figure it out and redo it all.


Using ECS, I even get pleasure from the refactoring process :) New features are easily added to the game, old features change - and all this without pain or conflict with the designer, who decided to add a new furious mechanics or remove old ones, playing around with them.


')

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


All Articles