Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

OOD could it provide a light-weight system with the benefits of ECS and OOD?

Discussion in 'Entity Component System' started by Arowx, Oct 21, 2018.

  1. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Good article that compares good OOD and ECS: https://www.gamedev.net/blogs/entry/2265481-oop-is-dead-long-live-oop/

    I have issues with ECS it seems verbose and like using a blunt tool to do a good job, could a good OOP system do as well or even better and still provide the OO features that we can benefit from?

    Please read the article here is a graph from it that compares OO and ECS versions of a game framework...

     
  2. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    Note that Unity's ECS is not just the ECS way of coding. There's also the jobs system and burst compiler. All of these three have to be used in order to get the significant boost in performance.

    There's not much significant difference when you're just using ECS. You might as well use the traditional GameObject-MonoBehaviour way of coding if you're not going to use the jobs system and burst compiler.
     
    hippocoder likes this.
  3. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    It's not comparing with Unity ECS + Burst and jobs. It's nowhere near the performance of Unity's ECS as it is right now. Not even close.

    Aras presentation is about patterns in C++ for it, not Unity specific.
     
    Vacummus likes this.
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    It’s absolutley incorrect compare ECS and OOD, you must compare DOD and OOD, they both can implement ECS pattern. Main Unity ECS performance gain is DOD which gives great opportunities for SIMD, Burst and Job System.
     
    Last edited: Oct 21, 2018
  5. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    Hmm, I am with you there for the most part. However, my understanding of Unity's ECS is that most of it's performance gains come from it's cache friendly nature which is not possible with the traditional MonoBehaviour style. So you do gain huge performance gains with ECS even if you don't use the Job System and burst compiler.
     
  6. nttLIVE

    nttLIVE

    Joined:
    Sep 13, 2018
    Posts:
    80
    Not huge but you do get some advantages. Mainly the fact that the code is more readable and gets less convoluted that can already indirectly optimize code. I remember reading a post from a Unity Developer saying that even if you don't Jobify or Burst anything you get a bit of a performance boost. I'd have to look for the post again.

    But the question has a bit of weird context. I think a scenario where you would never find a way to Jobify or Burst anything in your code has to be extremely rare or non-existent.
     
  7. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    Check out the conclusion of this article from Intel doing a performance comparison between Unity's ECS, Job System, Burst, and traditional MonoBehaviors: https://software.intel.com/en-us/ar...tem-ecs-c-sharp-job-system-and-burst-compiler

    It's interesting to note that when they introduced ECS to the mix, it allowed them to render 3X more units on the screen. That's pretty huge. The article also gives me the impression that ECS alone gives you more performance gains then the Job System and Burst individually. Not sure how true that is, but given that ECS (Data Oriented Programming in general really) helps dramatically reduces cache misses (which is the computers biggest performance bottle neck) and allows for SIMD operations, I can see how that might be true (please, correct me if I am wrong here).

    More info on how important cache misses are to performance here: http://gameprogrammingpatterns.com/data-locality.html
     
  8. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    Can't really conclude that from the article because when they added ECS they used it with jobs. You'd need to do a comparison using ECS without jobs to see the benefits, because when you're using jobs without ECS, you have to do all the dependency management so it's not a fair comparison as it's always going to perform relatively poorly.

    From my own tests, the performance is nothing to write home about using ECS without jobs. The real benefits comes from combining everything together. ECS, jobs and burst are really designed to work together to really get maximum benefits.
     
    Vacummus likes this.
  9. You can stick to SOLID, it's good to
    - generate a ton of small source code files, so you don't know where is what anymore (you will give them silly names after a while, it's inevitable, especially if you're working in a team)
    - generate a LOT of small abstract classes
    - generate a LOT of small interfaces
    - generate a LOT of small function/method calls
    - generate a LOT of data-interfaces and/or references
    - oh I almost forgot the ton of messenger classes (or PODs or other similar convoluted OOP "best practice")

    In other words: tanking your system in virtual call table look ups and of course heap and stack allocations.
    And we really didn't talk about the impossibility to convert all of your data and OOP to cache-friendly.

    But at least it will be convenient for you to code your application, ultimately it's your choice, you want to squeeze out the last drop of performance from any hardware your customers may have or you want to work super-conveniently. (No one important will judge you, believe me)
    Or working as you see fit for a while and see what this whole ECS-Jobs-Burst will turn out at the end and decide later. (hint)
     
    hippocoder likes this.
  10. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    And ECS you end up with a system for everything that used to be a simple function call.

    Combined with having to make 'structs' for every function call / system and every struct must be different to prevent it's data being processed by another system.

    Also Unity did have some in build systems that would pick up and work on your data without asking permission to run.

    Now imagine when this is released on the Asset store and every developer writes their own systems working on similar data sets but with different functions?

    How will an animation movement system know not to pick up and work on the physics systems data...

    Could ECS end up with a mass of data types and systems most of which do the same things just for different aspects of your game e.g. animation IK, collision physics, mouse input, npc sensors could all run a system that just raycasts, only they work for different domains/assets within your game...

    Could optimising ECS not be about making the algorithms faster (that has already been done) but analysing, refactoring and pruning the duplicated data filters and systems in your game.

    OOD gives games a object based design structure that works well with the simulation nature of games but poorly with the cache processing of CPUs, however could ECS be used as the functional model within OOD so you can combine systems and data into objects.

    Let's say an object is a set of systems and their data that we put together because they reference a gameobject, surely there are benefits in design and architecture as well as ECS from a more coherent approach that brings together the relevant parts of a game entity/object?

    Or there definitely seems to be a OOD gap between Monobehaviour and ECS that could be filled by a good system that could make ECS faster and 'easier' to design and develop with, what do you think?
     
    Last edited: Oct 23, 2018
  11. Again, it's your choice what is more important to you: performance or your own comfort as a developer. You can choose.
    But if that helps, think about Systems as simple function calls. Whatever works for you.

    Yes? What's your point? One system for one combination of data. That's the entire idea of systems in ECS. Apparently you can't think in DOD, you keep applying OOP things on what you're doing.
    BTW, if you think it's bad, feel free to choose OOP any time, again. Just because you can't see the advantages or they aren't worth it for you others may see the point. So what is this all about?

    Same sh.t happens in OOP world as well, just take a look at 'Item' classes in Inventory and Character Controller assets. They should be the same, but everyone have their own implementation with different level of craziness. Good luck to make them talk on a not performance-tanking way. Been there, almost done that, got the t-shirt but I teared apart at the end...

    There is no gap in terms of code (aside the convoluted syntax, which will be addressed as Joachim told you already if I'm not mistaken).
    The filler between ECS and Monobehaviour is already exists, it's called Hybrid mode and you can use it. Although it lacks of real performance, because of a lot of things, including having OOP 'side'.

    I don't know what you mean when it comes to "easier to design". What is complicated? DOD? Systems? Or the relations between them? Could you please elaborate?
     
    RaL likes this.
  12. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    OK in an OO or just functional approach I can build up a set of functions/classes that work with the Unity API and do everything I need in my game. An OOD approach allows me to group things into groups with common features or that do common tasks.

    For example a bullet object hits a enemy ship, a OnCollision function is called and I can add code in a couple of lines to destroy the ship, boost the score, play a sfx and launch a particle effect.

    In an ECS world I would need collsion, particle, sound, score and destory ship systems and ensure that they all generate the correct data patterns to interact.

    ECS replaces function calls to trigger activity with the need for data patterns specific to that system.

    My concern is that as projects grow and the number of function calls increase the job of maintaining and extending these systems will grow exponentially.

    Say we add a mother ship to the system and it uses a different sound effect, particle system and score as well as triggering the end of the level. In the classic system I can achieve this by passing in different data and adding in a levelOver boss component with an OnDestory() method.

    In ECS I now need to update the data passed into 4 systems and add a fifth system for level over. So as a developer my task becomes more complex faster as the complexity of the game grows and the systems need to cope with more event types/interactions.

    Note also how now what would be a few lines of code in a single function is distributed across a range of systems and the interaction or what used to be function trace is not applicable as it's data generation that triggers systems to run.

    We have a whole set of tools as programmers that work great at tracking function calls, will there be similar tools available to track ECS system interactions?
     
  13. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    Hmm, one of the challenges with OOP is that you are coupling data and behavior (and that's even if you do it the right way by following SOLID principles and other best practices).

    With such coupling:
    - how do you go about ensuring deterministic behavior? Determinism is critical when it comes being able to run your code in parallel.
    - how do you ensure no side effects happen? On a small app, this won't be a big problem, but the bigger the app gets the more likely you are to come across bugs that are extremely hard to track down and fix due to this coupling. Functional programming for example solves this problem by decoupling data from behavior and making your behaviors immutable. Data oriented programming solves this by also decoupling data from behavior also, but instead of enforcing immutability everywhere, we just make our data smart and our behaviors dumb.
    - how do you scale your app without introducing large refactors?

    The SOLID principles help a LOT with reducing the problems faced with coupling data and behavior. But why not just go at the root of the problem and decouple the two to reap the benefits that functional programmers have been screaming about for decades now?

    These kinds of things are talked in great detail in the data oriented design book. Check it out here: http://www.dataorienteddesign.com/dodbook/
     
    M_R likes this.
  14. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    https://github.com/papers-we-love/papers-we-love/blob/master/design/out-of-the-tar-pit.pdf

    ^ Here is an academic article from 2006, called Out of the Tar Pit, that talks about how you can reduce complexity for your app by following functional programming practices along with a relational data model (aka, keeping your data smart and behaviors dumb). The DOD book I linked above talks in great detail about this article and how such practices along with high performance techniques can allow you to write code that is performant, scalable, maintainable and simple.
     
    M_R likes this.
  15. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    448
    It looks like you just do not like ECS and DOD. Things you are proposing go against DOD principles.
     
  16. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    I think it's more so that he has been struggling with ECS and DOD and is having a hard time seeing the benefits over OOD. And reasonably so mind you. It's hard to wrap your mind around DOD when you are coming from OOD background. And to be frank, there are not many good articles out there to help people understand the concepts and their benefits over more traditional programming practices. Even the articles I shared in this thread are very hard to digest. But ultimately, I think it's a good thing that he is challenging ECS, cause it helps promote discussion/debate around these principles, which helps us all learn from one another.
     
    Last edited: Oct 23, 2018
    IsaiahKelly likes this.
  17. slim_trunks

    slim_trunks

    Joined:
    Dec 31, 2017
    Posts:
    41
    Different sounds and particles would probably still be handled by the same systems. But I guess smart data was already mentioned.

    There's already a lot going on in this thread but I just wanted to say that it can be incredibly freeing not to be forced to use OOP for once. ECS may be a bit verbose right now but I think it is in concept way simpler than some of the arcane rituals you have to perform when writing OO code (SOLID for example).

    In an ideal future we would be able to write what we want without any artifical complexity added but I think the Job System, ECS and Burst are great additions to Unity that I don't want to miss.

    Edit: I also very much agree that this discussion is valuable even though I disagree with the hypothesis that OOP is easier to design with than a more procedural/DOD/ECS style.
     
    Last edited: Oct 23, 2018
    Vacummus likes this.
  18. slim_trunks

    slim_trunks

    Joined:
    Dec 31, 2017
    Posts:
    41
    Excuse the double post but I wanted to touch on this:
    There's two things that can address this.
    1. Better tooling for managing Systems. I think this one is obvious.
    2. Smarter asset design. This is the important one. Of course we will get asset packages with whole Systems and Components set up, but the smart thing to do for asset creators targeting ECS will be to make the underlying functionality easily accessible to the user (as static functions for example). Then the user can decide how much to depend on the design decisions of the asset author.

    Side note: isn't this solved by the systems working on different Component types and having Entities specifically tagged to be worked on?
     
  19. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    OK Say you hit a bug in a OOP program you get a stack trace of the functions called, let's say there are 5 functions called in this sequence.

    Now in ECS you get an error in a system, you have no function trace to backtrack where the data came from, how much harder will it be to find and trace the bug back to source?
     
  20. You're constantly talking about a system which is not even in alpha. It's preview. It's lacking a ton of things. They're working on it.
    But I wrote this to you countless times. You don't like it, move on.
     
    pcysl5edgo, RaL, T-Zee and 1 other person like this.
  21. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    I don't know man. There are developers here that are using ECS even when it's in preview in their projects that are in production. That includes me. It's risky but the state of the tech now is already pretty useful. If someone can't utilize the current tech well or can't find good workarounds, maybe that's on the dev, not the tech. You can complain all you want. ECS won't go away. Unity is already heavily invested in this so I don't think they will change their mind just because some devs are finding it hard to use it.
     
    nttLIVE, RaL and T-Zee like this.
  22. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    What if you could write an game class where every function that was attributed with ECS would be turned into an ECS system with Job integration and Burst compilation.

    You could literally convert your existing code base with a simple [ECS] tag*.

    The functions would have to not call other external none ECS functions or inline them and fill a few other criteria but as long as the data they get is all they need then your class could become an entire set of ECS systems.
     
    Last edited: Oct 24, 2018
  23. slim_trunks

    slim_trunks

    Joined:
    Dec 31, 2017
    Posts:
    41
    The classes would then have to adhere to some strict rules that are probably not in line with OOP.
    If they did, you'd probably get something that looks almost the same as a ComponentSystem class.
    So I don't know how much easier that would be.

    A good example for this is the FastNoise library that I used recently vs. the Mathematics.noise functions.
    FastNoise is very flexible but in a Burst world it's painful to deal with as it's heavily influenced by OOP. The tweaks I had to do now make it practically look like the inbuilt noise functions from Unity.Mathematics.
     
  24. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    969
    Clever idea. Hope that someone makes an asset with that functionality. Or you do it yourself now since you want it so badly. As of now, make use of what's available. It's hard, but it works.
     
  25. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    448
    But your code would have to follow rules ECS and job system requires.
     
  26. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    This sounds more like a struggle to reason about gameplay execution than an issue with ECS design. In classic GameObject paradigm, code execution is primarily event driven. This works well when the code is single threaded, but falls flat on its face when you add multiple threads into the mix. ECS, especially the optimized multi-threaded ECS implementation Unity is using, does not really care much for event-driven code. Instead, it is more about data transformation. But you also get the benefit of being able to completely control the execution order of your systems. It takes more upfront planning. As a personal example, I had to sit at a whiteboard for a couple of hours to plan out my game structure. But ultimately I reached a better design than had I jumped in with GameObjects.

    There is also nothing really stopping you from adding interfaces and methods to structs if that helps you reason about your game. And at the expense of cache coherency (but still preserving parallelism and Burst support), you can nest structs inside of other structs, which might just be the OOD pattern you are looking for. It is also worth remembering that systems can utilize OOP to great extent for code reuse.
     
  27. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    Just finished watching the live session of the Entity Debugger, and they announced support for being able to step through every frame and see how your data is being transformed by your systems. Super cool!

    I do want to point out that your thinking too much in terms of code, instead of data. In DOD, you don't step through code, your step through data transformations.
     
    RaL and hippocoder like this.