Advertisement

Entity Component Systems and Data Oriented Design

Started by September 25, 2018 10:12 PM
33 comments, last by Hodgman 6 years, 1 month ago
4 hours ago, noizex said:

And I'd gladly hear about the "right way" to do this, because if ECS is bad, bad OO is bad, then what's good? Links, blog posts, articles, code samples please. I'm a bit tired of hearing one side advertising some ultimate solution to everything and more (which looks kinda ugly and is probably just as unmaintainable as anything else as soon as it grew to something bigger than some bazzilion of sprintes rotating at once on the screen), and another side bashing this, and mentioning some proper OO code which I obviously had never an honour to see.

You'll see that pretty much anytime someone posts an article or discussion or even mentions the term ECS. It's a lightning rod for smug disdain and towering superiority from people on both sides of the debate trying to put out an air of being a crusty old experienced veteran who knows his shit. They'll denounce the other side using some vague, incomprehensible generality intended to make them look smart, but the real details and specifics tend to stay pretty sparse. It's just another holy war.

It is kind of funny how they praise the ECS over their old EC design. In practice the old EC approach was and still is very successful for them. Endless small games have shipped using Unity. In my opinion the simplicity was always one of the biggest strength of Unity, I am curious to learn how the new ECS will play out in the future for them and how many people will adapt to it.

I agree with earlier posters that there is no silver bullet. As game projects grow larger organizing code and data becomes a difficult problem. ECS is just one way of doing this and I have seen both good and bad implementations of this concept. In particular if systems in ECS can depend on each other the code becomes as 'spaghetti' as in a OO entity hierarchies from my experience. So just using ECS and turning your brain off will not result in great game code.

Advertisement

Putting github commits into a slideshow is a bit of an epiphany. Going to use that trick in the future for sure!

Personally I can easily imagine lots of ways to screw up the nice "DOD" code at the end of the slides, once more features need to be added. To me it seems like the goal of the talk was to denounce some old strategies and praise some new ones, where the strategies were OOP and DOD/ECS. The praise was about less/simpler code, less memory consumption, faster speeds, etc... But at the end of the day anyone could come along and just screw it all up, regardless of what acronym is used or what code "guidelines" or "rules" are in-place.

I really liked following along with the commits, looking a little at profiling results, and seeing incremental optimizations -- that was all cool. I also think the starting code was very much like what any sane person would start with, so that's good on the author as well. The parts I didn't like were references to silly acronyms, and praise for methodologies. Writing down rules and guidelines for new engineers is good, but once it becomes more of a day-to-day handbook, or the "10 Steps to Writing Good Code" it becomes a dusty and useless idea. The heavy inclusion of acronyms took away from the educational merit of the entire slideshow. Sort of like a, please give us your knowledge but not your religion/dogma, kind of thing.

On 9/26/2018 at 11:59 PM, noizex said:

And I'd gladly hear about the "right way" to do this, because if ECS is bad, bad OO is bad, then what's good? Links, blog posts, articles, code samples please. I'm a bit tired of hearing one side advertising some ultimate solution to everything and more (which looks kinda ugly and is probably just as unmaintainable as anything else as soon as it grew to something bigger than some bazzilion of sprintes rotating at once on the screen), and another side bashing this, and mentioning some proper OO code which I obviously had never an honour to see.

Umm... There's no posts before (or after?) yours in the thread bashing OO or ECS. 

I was critiquing the "traditional OOP" code in the talk, which is presented as being bad code - he deliberately starts with badly written code to simulate a typical real world project. It's frustrating to see every ECS presentation follow this same pattern of comparing itself against bad code of a different style instead of good code. It feels disingenuous that an apples to apples comparison is never used. That's not a slight against the design - it's complaint against the promotion technique. 

As for the OO code being bad- it uses OOP language features, but does not follow OOD design rules. This might be "typical" of code in the wild, but it's a bit of a misnomer to call it "traditional OOP". I'd call it "typical OOP bullshit". It's really great that Aras included a git repository and commits for each step - if you're interested I might take the time to do a blog, starting from the initial bad code, and fixing it to actually follow OOD rules. 

A short version off the top of my head though - "virtual void Update" is an SRP violation. Dynamic cast is an LSP violation. It violates the principle of preferring composition over inheritance. The broad base classes are ISP violations. It needlessly reimplements language features with runtime code. 

Basically, it disregards OOD theory, and abuses OOP language features in ways that the theory says not to... i.e. There's a difference between using OOP language features and using OO design rules. Yet, unfortunately it is 'typical' and 'common' to see such things. That's why I'm critiquing it - instead of encouraging people to actually learn the existing theory, these kinds of presentations encourage you to just move on to the next fad without learning any of the decades of background material. 

Likewise, ECS itself is also just an ad-hoc reinvention of relational data modelling. By presenting it as some new pattern, it discourages new learners from actually bothering to study the underlying decades of formal study in relational techniques. 

Aras at least hints at this when he says that an entity is a primary key, which is far better than what most ECS talks do. 

TL;DR: study OOD, study SOLID, study relational data modelling, study object modelling techniques in general. There's decades of formal computer science research here. Most code that uses OOP language features doesn't actually follow OO theory. ECS is not a formal pattern, it's just a new buzzword name for using relational modelling, except with the added restriction that you can only ever have a single primary key (the entity ID), which isn't a necessary restriction to adopt. Relational is great. Procedural code is great. DOD ideas are great. OOD ideas are great. OOP tools are often used badly, bit not necessarily. ECS frameworks are often bad too, but not necessarily. Relational frameworks power a boatload of the internet (obviously useful). Bad code in any paradigm is bad.

2 hours ago, Hodgman said:

As for the OO code being bad- it uses OOP language features, but does not follow OOD design rules. This might be "typical" of code in the wild, but it's a bit of a misnomer to call it "traditional OOP". It's really great that Aras included a git repository and commits for each step - if you're interested I might take the time to do a blog, starting from the initial bad code, and fixing it to actually follow OOD rules

I, for one, would be quite interested in this.  I spend a good chunk of my day reviewing code at work for poor design decisions that violate SOLID principles, and it'd be nice to see your point of view on what constitutes a violation of SOLID and ideas on how to best repair those violations.

11 hours ago, noizex said:

I'm well aware there are no silver bullets, I just don't know if bashing one solution because it skews OO without showing the actual solutions which work or show the OO as it should be helps much. Most of discussions about ECS turn into argument how bad one or another side is, so there must be some practices that are in "the middle" and that could form a good toolbox for engineering solutions for our needs - I'd love to hear what are these. 

And funny thing you mention Ruby on Rails, that's what my team is doing in my day job, but I think you kinda drifted with that analogy... And of course there are arguments over which framework or solution works better - I just suggest to make this more... productive? so we could share the good practices and solutions? Not expecting silver bullet here, what Oberon accused me for. "Take ideas from something and something and use it to your whatever" says nothing really. We have a real problem here - management of entities and their logic in a game world. Of course this will be different for RTS strategy vs. race game vs. open world RPG. But if that's not good, then what is? Most of 3D games nowdays require some kind of 3D world filled with objects that are processed by some logic - lets discuss this and ditch all racers, platformers etc. which may require something slightly different, and talk what is better than ECS, data-driven or badly-OO-based one...

I've been trying to say that these are only tools, whether it's the pattern, framework, even 3rd party you will use even in form of full software. Trying to find a middle ground for everything will always lead to holy war, and most often it doesn't solve anything nor it's productive until it's particular to your own real problem, at least to me. ECS itself has been discussed here many times here, and the replies have been pretty much the same so far.

Advertisement
12 hours ago, Tape_Worm said:

I, for one, would be quite interested in this.  I spend a good chunk of my day reviewing code at work for poor design decisions that violate SOLID principles, and it'd be nice to see your point of view on what constitutes a violation of SOLID and ideas on how to best repair those violations.

Likewise. It would be neat to see the same code refactored into multiple different styles, actually. Rework it into "proper" OO, rework it into a relational model, rework it into a functional style...

19 hours ago, Tape_Worm said:

I, for one, would be quite interested in this.  I spend a good chunk of my day reviewing code at work for poor design decisions that violate SOLID principles, and it'd be nice to see your point of view on what constitutes a violation of SOLID and ideas on how to best repair those violations.

Ok I made a start on this and it looks blogworthy :D Basically if you fix the obvious OOD rule breakages in the original code, it's smaller/simpler than the final "ECS" version, uses less memory, initializes faster, and only updates slightly slower (due to no DOD cache optimization pass being done, yet)... This is a much more apples to apples comparison between OOD and ECS, both starting from the same "incorrect OOP" baseline:


Final "ECS": 1ec7f855bff5f15f2e1483f31a870d0813070115
Initialize time: 246.0ms
Update time: 40.1ms (1000020 sprites)
219.5MB
377LOC

/\
||
Original "bad OOP": 3529f232510c95f53112bbfff87df6bbc6aa1fae
Initialize time: 1061.8ms
Update time: 481.1ms (1000020 sprites)
389.3MB
400LOC
||
\/

Fix OOD violations: 264671e635b734879e50f4c93a79f9c4ec5ba5da
Initialize time: 141.3ms
Update time: 45.6ms (1000020 sprites)
158.6MB
322LOC

I'll see if I can pull a blog / github together over the weekend...

I'm a bit tempted to do the same thing, now that I've read the code in question. I can see what the author is going for, but I don't think it's really there yet. For starters, why are the world bounds in their own component? Just for the sake of making the code look like Unity scripts? And why use "structure of arrays" for the avoidance system? Why does the glue code have so little actual logic in it? The final "ECS" looks like a direct translation of the Unity-style code into structure-of-arrays without changing the actual decomposition. Maybe that's the point?

2 hours ago, Oberon_Command said:

The final "ECS" looks like a direct translation of the Unity-style code into structure-of-arrays without changing the actual decomposition. Maybe that's the point?

Yeah that is the point. You've got some terrible "dynamic composition system" code and want to convert it to "ECS" code in a series of straightforward steps. 

This topic is closed to new replies.

Advertisement