4 ms·
Whether or not to make your game have ECS has been debated for years, probably rightfully so to some extent. I ended up writing something like this myself for m
by Athos_vk 6y ago
Whether or not to make your game have ECS has been debated for years, probably rightfully so to some extent. I ended up writing something like this myself for my own 2D game engine. To name something, it's greatly decoupled, but it also means any algorithm (i.e. system if you will) can literally access any data from any object in your gameworld. It just breaks encapsulation to a huge extent, any data you add is immediately visible to every of these systems and in most cases, you cannot reason what inputs/outputs a system really has. That at least goes for the generic solutions out there.
However, I think this blogpost tries to argue against ECS for all the wrong reasons. I'm not going to go into every detail, but let's start out with this: I don't want to bash on Godot, I think it's amazing they're pushing the game engine scene, but a blogpost like this really makes me question the quality of what they wrote.
> Inheritance is more explicit
I cannot remember a time I ever found it useful to look at an inheritance diagram that presumably will be littered with diamond patterns. Besides, inheritance isn't immediately excluded from other codebases, it just isn't the core principle of their software design for composing objects. Also also, I might have hundreds of (slightly) different objects in my game, so even without diamond patterns, that inheritance hierarchy is not going to be very useful to me.
> Scenes are more explicit
I'm looking at the picture and I'm not sure why I want a scene graph to show my inheritance patterns in the first place! If you ask me, it clutters the scene graph with details about this object. I mean, not unworkable, but I cannot understand this is an advantage. Besides, easily replicated by listing the components that an object is composed of in any game engine, it's not like other editors/game engines can't do it. Most engines do this with a separate view that shows all the data for this object.
> Re-usability improves
This one is beyond hilarious if you look at some of their source code. The 2D vs 3D is a prime example, take audio_stream_player_2d/3d for example. A lot of the functionality has been copied between their counterparts (with some inconsistencies, of course). That's kind of logical from the structures, since the algorithms and data they operate on has been completely sealed off, so they couldn't even decently share it if they wanted to. It seems completely due to the fact that at the top of the hierarchy sits a hard distinction between 2D and 3D nodes.
To then point out you don't even need something like prefabs (for those not familiar: think of a template/blue print of a pre-composed entity with data already filled in) is just a weird stab. You could just as easily create such a pre-composed object in code with any component-like design, Unity's prefabs just give you the flexibility to compose these in the editor instead. How is an architecture where I need to explicitly type code to compose new objects ever easier than that?
There are other things I'd find questionable by a quick glance over that codebase that are also a side-effect of these architectural choices. Like, singletons that are used to combine nodes of the same type to form some spatial datastructure, because those nodes cannot be easily made aware of each other. There seems all kind of implicit dependency issues and I've always struggled with nicely engineering dependencies in such architectures as well.
But I'm going to stop here, there's just too much I can go on about in this blog (I would even consider dedicating an entire blogpost myself breaking my disagreements down).
The whole tone of: we use inheritance and we think it's better for the entirety of our software is just strange. As always, inheritance is a tool, you should use it when it's right, yada yada. If you use multiple inheritance and end up with diamond patterns, I don't think I'm the only one that would say that you should reconsider. Shoving all your logic for every aspect of your program into single objects has rarely worked well either.
I already mentioned what I dislike about the generic ECS that everyone keeps talking about like in Unity, but they can improve their architecture and/or apply DOD without doing a 180 into that direction. This weird deflecting of potential architectural flaws certainly didn't sell Godot to me, but hopefully they come back to this post and think it a couple times over.
- codeflo 6y agoMy experience here is very limited, but at least in the Rust world, some ECSs seem to make component dependencies explicit, partially to support scheduling parallel systems execution. That is, if there are two systems where neither system writes any component that the other accesses, they can run in parallel. Is that not common in general? Godot usually gets a lot of praise of HN and elsewhere, probably rightly so. But I got the same weirdly defensive vibes from reading the article. Performance is the strawman used throughout: claiming you don't need that many objects anyway, claiming that there design is "higher level" -- without ever really explaining what that means. I know from other contexts that the real problem with deep inheritance hierarchies often is code duplication, you simply can't solve the diamond problem. Good job pointing out examples of that.
- Athos_vk 6y agoIt's indeed a common approach that they list their dependencies so you can build runtime DAGs for multithreading, but my main point is that within one system dependencies can be selected at will (I believe Unity allows to just change these at runtime as well). In the end they just get the entire gameworld fed in and then select what they need. If you take something like writing unit tests, you basically have to mock the entire gameworld because these dependencies could change, even if only theoretically. I struggle to find a good way a generic approach of DOD can prevent that. In general it's also very hard to get dependencies done right. I think Unity does it well, but from what I saw some years ago it's one of few (for implentations that are public). Also not surprising considering Mike Acton seems to play a significant role in that. Yeah their arguments on performance are an even worse aspect of the article. It's clear that no game or simulation of significant scale has been built with Godot.