Why isn't Godot an ECS-based game engine?
godotengine.org
godotengine.org
Inheritance based: you derive Vechicle, then derive Tank, Car, etc. This was most used from 95 to 2005 as teams moved to C++.
Component based: you create a TreadsMovement component, a Turret component, a Wheels component, a Chassis component, etc. Each contains the data and behaviour for what they represent. You compose them together at runtime inside Entity objects to create tanks, cars, etc at runtime. Popularized by Scott Bilas' engine for Dungeon Siege. This is classic Unity. Most used from 2005 to today.
ECS: data-oriented where components are data-only, and behaviour logic lives in systems that act on a set of instances that contain certain subset of components. Entities are just ids for the set of components that make up the data for a given active object in the game. Entities and Components are best understood as a database which systems query and select from.
I don't know enough Godot to be sure if it's Inheritance or Component, but I know I left "classic" inheritance based behind almost 20 years ago and would never want to go back. Even back in 1997, the Commandos 1 engine was already half Component-based (but it took us a while to refine the Component model and intercommunication).
Back in the day, composition was referred to as "component-based entity systems", which makes perfect sense.
But then Unity came in and called their data-oriented one "entity component system" for reasons I will never understand. Why not just call it "data-oriented entity system" or something like that?
So nowadays when you hear "ECS", it's not clear what people are talking about anymore.
Also, to be fair, they really do refer to it as DOTS -> Data Oriented Technology Stack (granted, it includes more than just that), but I'm not sure if and when they changed that. Their community just seems to keep calling it ECS regardless.
Godot is a Unity clone. Unity has copied a lot of things, including Flash (and therefore Shockwave), where this "attach scripts to stuff" architecture actually came from.
Having used Unity and Godot, I really like the architecture of Godot. But Godot is not nearly as fully functioned (yet).
Your dates are right too, at least from my experience during '04~'12. Being on the tail end of that inheritance based approach was brutal and was so happy to leave it behind.
Yeah I did code architecture work on Commandos 1, then led the tech & tools for the expansion and Commandos 2. A lot of the C1 work was related to this topic, actually: when I arrived at the project, it was hard inheritance-based with a fixed set of subcomponents, and I shifted it to a common base for gameobjects (the class "Bicho", really odd name) which contained a collection of arbitrary components that communicated via messages. It was more extensible that inheritance, but very messy - too many assumptions and typecasts. First steps... The Commandos 1 codebase was thrown away and restarted from scratch for Commandos 2.
If you ever get around to writing up a technical post mortem I'm sure it would be super interesting. The simulation seemed quite advanced for the low end hardware the game ran on, with view cones, pseudo height, physical objects, footprints, and pretty good AI.
The Commandos series dying out is a great shame, although of course Kalypso is staffing up to attempt a sequel.
What are you up to these days?
For the past 2.5 years I've been at Lingokids, a mobile service filled with fun and educational content for kids in English. The tech challenge here is balancing constant forward movement with new games, while keeping all the previous ones working. But using my kids as testers beats anything else I've ever done in the fun-at-work department.
https://store.steampowered.com/app/1227530/Partisans_1941/
I can definitely see that being more fulfilling. There are only so many virtual Nazis you can kill before it wears thin!
Make that nothings' and MAHK's http://enwp.org/Dark_Engine for (initially) Thief.
The article says that "Godot does composition at a higher level than in a traditional ECS", but I don't get what he means by that? Combining nodes with incompatible hierarchies is hardly composition, and is just what you typically have to do when using inheritance.
Inheritance-based entity systems are not always terrible, and even though I tend to hate them, I use them quite a lot in my projects where an ECS would be overkill. If designed for a particular project, you can usually be more productive, and write cleaner and less code with inheritance.
However, for a general purpose engine like Godot, that's a bad choice IMO. The flexibility offered by an ECS far outweighs all benefits of an inheritance-based system.
Instead of “this thing uses this subset of parts from its parent” it is “this thing is composed of this collection of parts.”
With everything inheriting from the Node class, I've only seen it as being an OOP/inheritance system.
For performance at least my focus is usually on eliminating information-lossy interfaces i.e. try to keep the hot loops where the compiler can see them
So, yeah, try it. It's the best system I've encountered for the general-purpose use-case, and I've designed a fair few myself.
well, I'm glad you're describing the way you see the tradeoffs, I just have a hard time seeing how hanging your hat on the ability to eek out every little bit of resource optimization at the expense of early iteration is a worthwhile tradeoff for the majority of gamedevs. Running the game at a worse framerate or render setting so that you can tune the gameplay early, get through many different gameplay design iterations, and get the artists and sound people working sooner seems like it would be of value to more teams than something highly performant that makes it harder to experiment and iterate. (on the ECS vs inheritance point I'm in agreement.)
The origins of ECS are in the work of Scott Bilas and Adam Martin, who weren't seeking performance improvements, but rather a way to allow non-technical teammates to iterate faster. This thing was revolutionary in the late 90s/early 2000s because suddenly you didn't need an army of increasingly expensive programmers just to get simple things done.
The performance boost was discovered much later when people found out that ECS could naturally benefit from data-oriented design. Performance is a nice-to-have but is far from being the raison d'être of ECS. It still makes sense to to have ECS or EC (or even just non-inheritance-component-based, like Unity) without the performance advantages of data-oriented design.
"Component Software: Beyond Object-Oriented Programming", 1998
The claim of Godot having similar tools as other engines certainly caused me to raise an eyebrow.
The strangest in my mind, however, is trying to downplay the importance of the performance advantages by claiming games with many objects are rare. I currently work on optimising a game which falls somewhere between indie and AAA. We have thousands of objects active at any given time.
I also dislike the statements regarding compute. I love compute shaders and use them whenever I can, but they're basically unusable from a performance perspective on both mobile platforms and Nintendo Switch.
(Edited from a Reddit comment I made regarding this article)
Which games in https://en.wikipedia.org/wiki/2020_in_video_games have thousands of live objects?
Objects are anything from walls and NPCs to sprites, particle effects, imposters, ... they pile up very quickly in a complex scene.
Had an engine where each entity could only have one mesh object since it was a part of the base entity type rather than a component. Led to a lot of multi-entity shenanigans that were brutal from a sync/off-by-one-frame perspective.
Using ECS
Nothing prevents you to use an ECS solution in Godot. In fact, I strongly suggest to check Andrea Catania's fantastic work on Godex, which aims to bring a high performance ECS pluggable implementation.
At the moment Godot is really only viable as a 2D engine, as it tends to bog down when used as a 3D game engine even though it has all but replaced the default Blender engine (their recommendation). So in order to get a viable 3D project, a user would have to use an experimental ECS version (no offense to the creators, they are working hard and I do have high hopes for this project. I'll most certainly be experimenting with it) using the C# version, which is still fairly new.
Now, the fact that a small group of devs can make an indy project/proof of concept with Blender and Godot, or students can make a group portfolio that is viable - these things are AWESOME. Granted. But it still comes out of a quasi Frankenseinian lab as they have chosen to go with OOP instead of ECS, it seems, even though a path does seem laid out before them.
P.S.
here's the link to the ECS project:
Seems to be a guy, Andrea is a male name in Italian, and female in pretty much any other language.
Everything was dynamic, read from data definitions when the game loaded.
One downside to godot’s inheritance is everything is set up in code and decided at compile time instead?
Its kinda like the config file vs code as config debate. If I where modding something I would rather have a full programming language than just a config file, but the config file does make it easy to do simpler things without breaking stuff, the more complex the config becomes the closer to a full blown DSL it is and you might as well just use a mature scripting language instead.
I had trouble parsing this because I was reading "vs code" as visual studio code.
> If I where modding something I would rather have a full programming language than just a config file, but the config file does make it easy to do simpler things without breaking stuff, the more complex the config becomes the closer to a full blown DSL it is and you might as well just use a mature scripting language instead.
I think using a mature scripting language is just a matter of transferable skills. People may be more reluctant to learn yet another language just to mod your engine. Especially if it's a one-time thing.
They just usually ship as side effects of that process, because no body really cares that much for single player games.
That's not really the case because Godot can load scenes at runtime. The scene format itself (.tscn files) is text based[1] (which is also nice for version control) and could be edited by hand, then loaded into the game at runtime. Though since the Godot editor is open source and totally free it would probably be better just to ship that with the game. It's also really easy to extend so custom game centric plugins that modify the editor itself are also easy to write.
1: Here is a sample scene file, just to give a sense of the format:
$ cat enemies/bandit/BanditSpread.tscn
[gd_scene load_steps=2 format=2]
[ext_resource path="res://enemies/bandit/BanditBase.tscn" type="PackedScene" id=1]
[node name="BasicBandit" instance=ExtResource( 1 )]
fire_period = 0.85
[node name="VK-001" parent="Sprite" index="6"]
visible = true
[node name="LG-Anger" parent="Sprite" index="8"]
modulate = Color( 1, 3.1875, 6, 1 )
[node name="ProjectileWeapon" parent="Hardpoints" index="0"]
projectile_spread_degrees = 60.0
projectile_variance_degrees = 0.0
num_projectiles_min = 6
num_projectiles_max = 6As much as godot wants to claim their nodes are lightweight, ending up with so many redundant tramsforms, vtables and more (see their Node3D class) just shows how inflexible it is. Again in engines like Unity you can take the exact same approach, they just allow you to author entities without this redundancy.
To add: the blog specifically mentions that using inheritance is used for better re-use, but the need for having this composition through nodes would take that away. I know this might not be your specific point, but it ironically makes it seem they don't see this as an alternative.
It's all about having configuration data separate to the logic. And use this data to setup and build the game elements.
Here's a couple of videos I created:
How to start with Data Driven Development in Godot: https://www.youtube.com/watch?v=ZG__fXSp74c
What I can do with it in my game, One Way Dungeon: https://www.youtube.com/watch?v=PqZwKahZ3cU
The former is a methodology for building engine systems that are cache-friendly, the latter talks about workflows that are more flexible to artists and developers.
You can use ECS without "being data-driven", and you can use data-driven workflows without ECS.
True, I've read about ECS being used for one or both of those purposes.
My first contact was ECS was as a composability pattern. So, in a "high level" purpose, as an alternative to inheritance. It was also described as "Game Object - Game component" pattern.
See http://gameprogrammingpatterns.com/component.html, specially the sidenote in http://gameprogrammingpatterns.com/component.html#no-bj%C3%B....
There's the "performance" ECS, where it tackles data locality.
And the "game element definition and configuration" ECS, where it solves a high level problem of building game elements. On the "game developer" level, Unity works like this.
The coolest 80s trick was rotating the palette to get moving water.
Allows you to pair Rust with Godot comfortably via gdnative.
Then use one of the good ECS systems in Rust like -
https://github.com/amethyst/specs
or (archetype style ECS)
https://github.com/amethyst/legion
To get spun up on ECS in Rust I suggest -
http://bfnightly.bracketproductions.com/rustbook/chapter_0.h...
This won't get you a godot project but will get you a basic concepted game you can then port into godot-rust.
However I found it nearly impossible to integrate into libraries/engines that aren't made for it.
I really wanted to use React for my complex RPG UI and PhaserJS or Pixi for I/O, but the state management paradigms just didn't work together (for me at least).
What issues did you have?
Messaging is ideal for decoupling, sending/receiving data and it makes networking parts of the game much easier.
Every game engine or system I use I set it up this way. I always make my components or entities data backed so when people say you can't have data-oriented in GameComponent systems it seems they haven't done much game development. I usually have most of it in JSON and in previous engines INI was popular (Unreal still uses this for some and lots of custom engines). I have always separated data from the objects, lots of people do not and that is why this is a major debate along with all the talk around it due to Unity adding their ECS. Data should always be separate from code and hopefully merged at runtime.
The benefit of ECS is performance alone and usually only really needed for high performance real-time or physics heavy games for parallel performance and essentially pre-optimized for batched mutations or changes, everything else can be done across the same from messaging to data backed entities/objects/components and more.
I do wish engines were better as abstracting these elements away. Lots of the systems start leaking into the engine which is supposed to abstract these elements away in a good pluggable/versioned/atomic game engine.
Like what Garry said about Unity [1], too many things are leaking up to the game developer creating all these debates and issues and incompatibilities. The fact this isn't just a switch or setting to switch from GameComponent to ECS is a problem. Same with incompatible renderers and more, those should be wrapped and pluggable with the same surface level method signatures and objects. Underneath is where all the tech needs to go. Leaky abstractions are a problem across the software world right now.
Atomic systems with facades that wrap complexity and are able to be swapped beneath the surface are fading and making things more complex than needed. The job of engineering is taking complexity and making it simple, not the other way around.
It's not clear from the article how Godot entities are organized in memory or if there is even is an abstraction layer between logic and data.
But if you have multiple systems (say collision detection, physics, damage/health, control(ai or player)) you can then build things up lego brick style.
For example, a basic wall will just participate in the collision detection system and nothing else, but now it's easy to add in breakable walls by giving them a hp value and defence value for the damage system.
Does that help?
The goal is to have "Systems" which operate on "Components", and "Entities" are completely out of the picture. The idea behind Systems is that they operate on a continuous block of memory:
for (auto &damagable : damagables) {
damagable.hp -= damagable.damage_this_frame;
damagable.damage_this_frame = 0;
if (damagable.hp <= 0)
damagable.dead = true;
}
for (auto &movable : movables) {
movable.position += movable.velocity_this_frame;
movable.velocity_this_frame = vec3(0);
}
Simple toy example, but by splitting up the data based on what acts on them, we have two loops that are very cache-friendly. Each of those two loops is called a "System".The System is the key part of ECS that makes this work. Just splitting off components and still using a virtual update function isn't going to get you any performance benefits, but it's still most of what I see when I see "ECS" talked about online. In fact, making components contiguous while leaving your updates to be whole-entity-at-a-time is going to make your cache coherency worse!
Entities, then, are actually not "container objects", but often just uint32's -- all of their data is inside the Components. The database analogy: The Entity is just a primary key tying together a database of tables (Components). The tables can be acted on, sometimes in parallel, by Systems (UPDATE queries), regardless of the originating Entity.
Actual Systems in practice have dependency chains and other things, to make sure that updates are done in the right order, scheduling mechanisms, and ways to make cross-component talking safe, and performant.
Unity's GameObject is not ECS, despite it being an "Entity-Component" model. Their new DOTS stack is, but it has tradeoffs for that performance.
Put simply, "EC" is a way of structuring your data classes to not rely on inheritance, "ECS" is a way of structuring your algorithms that act on those data classes to not require virtual methods.
The rest of this thread has similar misconceptions, and even the original post makes some errors too. Sadly, this misinformation is widespread, and it's not really correctable at this point. Oh well.
Actual Systems in practice have dependency chains and other things, to make sure that updates are done in the right order, scheduling mechanisms, and ways to make cross-component talking safe, and performant.
Do you know if there is a formal term for this kind of dependency chain and update order scheduling is called? I’m interested in ways this kind of checking can be done at compile time, or at least a run time guarantee that things won’t be done in the wrong order and fails to compile/generates run time errors when you have a cyclic dependency rather than having to map that all out by hand.
ECS might make this an independent-enough concern that techniques from build systems would be applicable. See "Build systems a la carte" [0], for instance, which captures the (an?) essence of build systems as managing a graph of dependent dataflow processes. (In ECS, the dataflow would be mediated by the database of component tables, just as in Make the dataflow is mediated by the filesystem.)
[0] https://www.microsoft.com/en-us/research/publication/build-s...
You need to use a programming language like C++ to be able to this. In JavaScript, all objects are pointers, so there's no way to do this.
Google "data-oriented design" to learn more.
Consider the difference between:
object 1
property A
property B
object 2
property A
property B
and: property A of object 1
property A of object 2
property B of object 1
property B of object 2
If you need the property A for all objects, in the first example we have to jump over the property Bs. In the second example all property As are next to each other.In a language where arrays are not sparse, but rather dense, the whole array is allocated as one contiguous stride of memory. Iterating through it is very fast, because the CPU cache hits every time and the next data you need is always ready, as it immediately follows the previous in memory.
Additionally, ECS wants to pack data even further, so that unneeded data is not interleaved within the memory stride at all. Every byte you "skip" is wasted space in the CPU cache, and eventually accumulates into a full cache miss, which stalls program execution.
In the ECS project the notion of 'thing that can run into other things and do damage' so totally separate from the notion of 'thing that is driven around by AI.' So adding guidance to an existing projectile wasn't too much of a pain. In the Godot project I'm dealing with networking as well, so the division is between fire-and-forget projectiles (derived from Bullet) which know about hitting things and doing damage, and AI driven Ships with AI or player driven movement which needs to be synced over the Network. In that case I had to copypasta the AI driven movement code into a 'guided' class under Bullet. That said, for almost every other task, Godot's composition first model has been way easier to work with, especially because it lets you test elements in isolation. Here are the two projects if you'd like to compare the code:
Homebrew ECS framework on top of the babylonjs engine: https://github.com/EamonnMR/Flythrough.Space
Godot with networking: https://github.com/EamonnMR/mpevmvp
My game objects always look more like Celeste's Twitter-infamous Player class: https://github.com/NoelFB/Celeste/blob/c32f134d210fcf710d750...
Say about the length of the file what you want, but isn't it actually better for caching that all of the Player's instance variables are in one object, and not stored in components somewhere else?
(Now, maintainability is another issue. But I've always found Ruby-style mixins much easier to reason about than the toy ECS systems I've seen.)
Physics, AI, animation, etc.
A player controller is not a good candidate for that type of optimization because they tend to have very complicated logic that needs to interact with many different game systems. Also, you don't usually need to have more than one or a few.
That class you linked to is a mess because it seems like all state is mashed together into a single class. One way to clean this up is to implement an object-oriented state machine, so that state variables and logic are organized into classes instead of being a conditional soup in a giant update function. Here's a good article on that: https://gameprogrammingpatterns.com/state.html
But that game shipped and it worked, and that's really all that matters.
That sounds good, but how would this look like in practice? For the sake of simplicity, let's assume I write a 2D game with classic spritesheets for animation frames. With an ECS, I can pool the animation state of each object into the animation system, and basically execute "anim_frame = (anim_frame + 1) % num_frames" for all objects in one speedy loop.
But game object animations are tied to game logic, and as soon as an object depends on its anim_frame in logic that is outside of the animation system, the cache benefits are moot.
Maybe I'm not thinking big enough in terms of how many "dumb" objects are in the game in proportion to the ones that have lots of logic (like the player).
But imagine a simple 2d game: whag are you reusing on a lot of entities? - collision size - sprite to render and render properties - position on grid - maybe also a velocity, maybe an acceleration
With ECS it becomes trivial to make a system that iterates over all entities with a sprite and a position, and draws them. Another system can adjust the position with the velocity. Notice how we can create non-moving entities by not having the velocity component at all. Also notice how we can easily add a rendered sprite to any entity without changing any code.
I know this scales well as it gets more and more popular also for larger games.
Bonus: This data is all located together so iterating over Sprite+Position is very cache friendly. And if a system only reads and writes data to the entity jt can also be parallelized.
This is the way. I have spoken.
For example, the article mentions that for simplicity some components require other components to exist. That sounds like something that cannot be encoded in the type system of most languages, whereas the fields present in classes within a class hierarchy are encoded in the type definition.
A code example would help me figure out if I'm following or not.
[RequireComponent(typeof(RigidBody))]
public class MyObject : MonoBehavior { /* ... */ }
This is not really in the type system, but still, if your language provide some meta-programing features, it can help the developer makes sense of your code.This kind of dependency is not a "type dependency" IMHO, since the data are independent of each other. It's more like a "logic dependency", where the logic of one System requires the logic of another System.
It is the systems you want to apply to an entity that will dictate what components it needs.
Since it can change during runtime, this cannot be statically typed.
Suppose we have two components: A and B. A is defined to `RequireComponent` B. If I do `has(object, A) && has(object, B)` then can the C# compiler compile away the check for B given the check for A, turning it into just `has(object, A)`?
IIRC, all "RequireComponent" does is allow you to omit the "add(object, B)" when you "add(object, A)".
A simple example of this is when you add A to the object, then edit A to require B. The Unity Editor won't add B automatically (which is in fact a pain).
NB: removing A will not remove B, and B won't be replaced if it existed before.
I usually use "RequireComponent" whenever I have a "GetComponent<...>()" in my behaviour just to make sure I have an initialized value.
Although I don't know much about entity component systems, my impression is that it is basically just multiple inherentence. Personally, I never had any need for such a thing in Godot.
tensorflow has python frontend and that is "slow" too, yet it doesn't matter because most of the work is done in C++ and python just compiles that graph to something lower-level
The choice of inheritance vs. composition is not a dichotomy, it's a spectrum. There are certain properties of your program that are better modeled through inheritance, and others that are better modeled through composition. You end up using both in the vast majority of systems.
Classical object-oriented GUI frameworks have a Button class that inherits through a chain of classes that add greater refinement of behavior. See [0]: System.Object -> Component -> Control -> ButtonBase -> Button.
But you don't create such a hierarchy for something like a login form. A login form will inherit from Form [1] and use composition of subcontrols to create its behavior. You'll have a few textbox controls, a few labels, and a couple of buttons composed with the login form.
And neither is an Entity-Component system really all that great of a composition system. You end up having to query the system for cross dependencies at runtime a lot, as there are no compile-time, static guarantees that any particular component will exist. Something like Inversion of Control with Dependency Injection can give you a better workflow for getting dependent components together in the same place.
Incidentally, building a project in an Entity-Component system (or any composition-based system) does not prevent one from being able to utilize inheritance, either. I'm not even aware of any composition systems that don't use inheritance heavily, actually. For example, Unity's ScrollView [2] component has the chain System.Object -> CallbackEventHandler -> Focusable -> VisualElement -> ScrollView.
An Entity-Component system is really much more about creating ad-hoc objects. Game design is notoriously finnicky. There is no schema or "shape" of fun. You tweak and reorganize and tear apart and recombine things until it just "feels" right. So Entity-Component makes it possible to create and compose objects on the fly, with fairly reasonable performance.
So these statements like "I turned away from inheritance 20 years ago and I'm now all about composition", they just don't make sense. "Inheritance vs. Composition" is not something you think about at the application level. It's something you think about at the functional unit level, and make the choice separately for every functional unit.
[0] https://docs.microsoft.com/en-us/dotnet/api/system.windows.f...
[1] in WinForms that'd be: System.Object -> Component -> Control -> ScrollableControl -> ContainerControl -> Form
[2] https://docs.unity3d.com/ScriptReference/UIElements.ScrollVi...
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.
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.
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.
the problem of that kind of engines is the users are computer-illiterates
they don't understand how memory/cpu works
what happens is 90% of 3D indie games suffer from major performance/optimization issues
and we start to see the same kind of performance issues in AAA games, because, as always, we always want to cut costs, everywhere
worse, clueless people are gaining power and are getting into high positions, and they hire more clueless people so nobody can oust them, or tell them they are wrong, they want people to comfort them, and defend their bad decisions
There are libraries enabling ECS for you if you are not looking for an engine like Unity:
C++: https://github.com/skypjack/entt (Non-Java Minecraft uses this)
Java: https://github.com/libgdx/ashley
Rust: https://github.com/bevyengine/bevy (it's still work in progress, not battle-tested and a moving target)
Although, arguably, Dungeon Siege's component architecture is different from what we call ECS today.
EDIT: I found the slides: https://www.gamedevs.org/uploads/data-driven-game-object-sys...
"Component Software: Beyond Object-Oriented Programming", 1998
It was pretty widely known in industry as a way to have cache locality and made it out to the broader dev community a good while after.
If you look really carefully you'll find structured column databases have similar properties since when you optimize for speed cache misses are your number one enemy.
About structured column databases, the same thing could be said about Lisps like Clojure which match the RMDB data model. But people still find it hard to grok it, hence the low adoption rate.
https://docs.unrealengine.com/en-US/ProgrammingAndScripting/...
The "S" in unreal is a tick. It's been about a decade since I last worked with Unreal but there was very much the concept of systems that processed batches of things in areas where performance was a concern.
Keep in mind that ECS is a design pattern and just like any design pattern applied blindly you can end up in a worse place than you started. A FactoryDispatcherQueuePatternImpl helps no one despite using many design patterns. When it comes to ECS it's much more about the spirit than the letter of the law.
But that's hardly "all the game engines"
I've seen metatables used often to implement inheritance, but not the ECS yet.
The coroutines there was incredibly useful, our designers could write AI that was almost literate programming(yield value was number of frames to wait to re-eval coroutine). Something like: Walk to point A, yield until at A, turn, walk to point B, yield, check for nearby entity of type, yield, etc.
Oh and it also ran the whole game state in a 400kb preallocated block in a system than only had 8mb of accessible ram(rest went to vram).
"Component Software: Beyond Object-Oriented Programming", 1998
The recent hype comes from Unity, because they very unimaginatively misappropriated the term.