HN Theater @HNTheaterMonth

The best talks and videos of Hacker News.

Hacker News Comments on
Overwatch Gameplay Architecture and Netcode

GDC · Youtube · 23 HN points · 24 HN comments
HN Theater has aggregated all Hacker News stories and comments that mention GDC's video "Overwatch Gameplay Architecture and Netcode".
Youtube Summary
In this 2017 GDC session, Blizzard's Timothy Ford explains how Overwatch uses the Entity Component System (ECS) architecture to create a rich variety of layered gameplay.

Register for GDC: https://ubm.io/2yWXW38

Join the GDC mailing list: http://www.gdconf.com/subscribe

Follow GDC on Twitter: https://twitter.com/Official_GDC

GDC talks cover a range of developmental topics including game design, programming, audio, visual arts, business management, production, online games, and much more. We post a fresh GDC video every day. Subscribe to the channel to stay on top of regular updates, and check out GDC Vault for thousands of more in-depth talks from our archives.
HN Theater Rankings

Hacker News Stories and Comments

All the comments and stories posted to Hacker News that reference this video.
Sep 08, 2021 · adampk on Unity patents ECS
https://www.youtube.com/watch?v=W3aieHjyNvw&t=1455s

"In this 2017 GDC session, Blizzard's Timothy Ford explains how Overwatch uses the Entity Component System (ECS) architecture to create a rich variety of layered gameplay."

(My favorite resource to explain ECS + NetCode)

Sep 07, 2021 · Rd6n6 on Unity patents ECS
Isn’t there a ton of prior art? I’ve seen tech talks about ecs implementations for years.

From the top of my head, here’s a great tech talk about overwatch. https://youtu.be/W3aieHjyNvw

Here’s a tech talk by Bob Nystrom (the game programming patterns guy) that mentions ecs from years ago https://youtu.be/JxI3Eu5DPwE

Edit: letsInvalid in another thread above linked to an article from 2013: https://www.gamedev.net/tutorials/programming/general-and-ga...

Jul 06, 2021 · pphysch on Open 3D Engine
I'm seeing Godot mentioned a lot: one major distinction between O3DE and Godot is that O3DE is "ECS-based" while Godot is "OOP-based" [1][2].

This makes little difference for the hobbyist gamedev, but it has ramifications for large projects with many interacting systems. Proper ECS architecture better supports the latter case [3].

[1] - https://docs.o3de.org/docs/welcome-guide/key-concepts/#the-c...

[2] - https://godotengine.org/article/why-isnt-godot-ecs-based-gam...

[3] - https://www.youtube.com/watch?v=W3aieHjyNvw

chmod775
OOP with an inheritance tree is nice until you have a houseboat.
akx
But isn't a houseboat just a house that's built on a floaty boaty thing instead of solid ground? Sounds like composition ;-)
garmaine
That’s object inheritance that trips you up. Interface inheritance (a la Rust) handles this fine.

Edit: that’s a great witticism though.

fenomas
Dynamically though? The attraction of ECS is that your house can start and stop being a boat as needed.
garmaine
I don't see a theoretical reason why not, although I don't know of any language that does this. Isn't really my area though.
bmn__
Even languages with heavy-weight MOPs do not offer a programming interface to unapply/uncompose, the reverse of:

https://metacpan.org/dist/Moose/source/lib/Moose/Meta/Role/A...

https://github.com/rakudo/rakudo/blob/master/src/Perl6/Metam...

Reading the source codes, I think this is due to no one yet having requested the ability to do so. To me it feels like implementing this is possible, but tedious.

The simple work-around for the problem would be to rebless the instance. Example:

    class Structure {}
    role Floatable {}
    role Inhabitable {}
    class Houseboat extends Structure with Floatable with Inhabitable {}

    $hb = Houseboat new
    $s = Structure new
        $s apply Floatable, Inhabitable  # houseboat at run-time

    # stop swimming
    ### NYI
    ### $s unapply Floatable

    # make a new house that cannot swim
    $s1 = Structure new
        $s1 apply Inhabitable
        $s1 = $s rebless_into $s1
lizmat
I guess in Raku you would create a Boat role, and you would create a clone of a House instance with the Boat role mixed in, when needed.

In Raku speak:

    my $house = House.new;
    my $houseboat = $house but Boat;
See: https://docs.raku.org/routine/but

There would be no need to de-compose.

fenomas
But note that the point of an ECS is being able to dynamically change roles without recreating new entities. If changing a house into a houseboat means creating a new entity, then everyone who had a reference to the house would need to be informed of the new reference.
lizmat
Doesn't de-composing have the same issue, though?
fenomas
I'm not sure I follow. In ECSs that I'm familiar with, entities are integer IDs, not class objects. So adding or removing components (roles) to an entity doesn't make use of any language-level features, it's just calls to the ECS library. E.g. in JS:

    var id = ecs.createEntity()     // returns an int
    ecs.addComponent(id, 'house')
    ecs.addComponent(id, 'boat')

So, very different from the class-based approach being floated a few comments ago. Does that answer your question?
raiph
Liz suggested `but`, but that creates a new entity with the role mixed in.

Instead one can use `does` to mix in to an existing entity:

    role House {}
    role Boat {}

    my \id = 42;
    id does House;
    id does Boat;

    say id ~~ House; # True
(What's missing is the ability to drop a mixin once it's been added via `does`.)
EamonnMR
Godot is sort of its own thing, not a strict "object hierarchy everything" so much as "favor composition; everything is a node in the scene tree."
pphysch
Godot's head developer admits that if you want to do anything performance-intensive (e.g. thousands of interacting entities, AAA stuff) with Godot, you will likely end up hacking the low-level engine code or even using a separate ECS/DoD implementation. At that point, why not use a proper ECS engine?

https://godotengine.org/article/why-isnt-godot-ecs-based-gam... (see "Optimization" section and below)

flohofwoe
Hardly any game needs "thousands of interacting entities" though (outside of special subsystems like particle systems). Arguably, (DOTS-style) ECS makes it harder to incrementally build a game by adding features, because you need to put more effort into designing the data layout upfront. And if there's just a few dozen instances of each thing that's definitely overkill, moving to ECS won't make a noticeable performance difference in that case.
mkishi
I've been wondering something, though: wouldn't it be possible to implement regular EC-style components on top of an ECS system?

You can't implement ECS on top of EC, but if it's possible the other way around, Godot's argument that most people won't need it would seem a bit weak — just let them use fat components on top of an ECS core, and if/when they need the performance there's still room to push it without side-stepping the whole engine.

jbluepolarbear
You can implement ECS on top of EC. Entitas is and example of a really good ECS on top of Unity’s default EC.

I’m currently writing and designing a serialization/networking library that I’m using to build an ECS framework on top of regular Unity EC. Why not use dots? Well, I hate the restriction of using only blittables for component data, I want to have access to the already existing ecosystem of Unity packages, and the biggest is that I am designing it for networking first. It’s slow going (I’m a dad and I have a full time game dev job), but I’m making good steady progress. My serialization library currently features composition, quantization, no reflection, and no garbage collection. I plan on releasing the first version under the MIT license hopefully in the next couple months.

I have a prototype that I’ve been building to test my stuff. Check it out it’s only 30s. https://youtu.be/p4v3ZnS2KBM

prox
Your demo reminds me of a problem that M&B 2 Bannerlord had, they created a destructable castle, but couldn’t get performance network enough to sync the destruction (bricks and stone walls) to all players.
jbluepolarbear
Networking games is hard. It’s what I do for work and it’s an iterative process.

If you’re interested in the subject of physics and netcode I’d recommend: https://gafferongames.com/post/introduction_to_networked_phy...

If your want a very deep dive and very technical, I’d recommend: https://fabiensanglard.net/doom3_documentation/The-DOOM-III-...

A lot of good resources at the bottom of the pdf too.

prox
Thanks so much for posting these! I did get interested about physics, I recently did Space Engineers scripting and it really is cool to play with all kinds of variables.

Now learning Godot to be able to quickly learn.

pphysch
> Hardly any game needs "thousands of interacting entities" though (outside of special subsystems like particle systems).

This is an example of survivorship bias. How many ambitious game concepts have collapsed under performance/architecture issues that lead to productivity-killing refactoring? Impossible to say, but no doubt many.

> Arguably, ECS makes it harder to incrementally build a game by adding features, because you need to put more effort into designing the data layout upfront.

OOP bakes these decisions into the inheritance hierarchy, which ends up being more thorny than adding a component, or migrating an existing component's schema. ECS will make it straightforward to determine which Systems will be affected when a particular Component's schema is altered.

megameter
It's a "where are the bullet holes on the planes that survived" kind of problem. The thing that overwhelmingly kills game projects is overscoped design, which manifests into a need for very detailed, configurable entities with rich scripting functionality. So if you pursue scalability at the level of the entity system itself, as a thing you should invest substantial engineering resources to - you are effectively saying, "yeah, I have a team of 100 people to throw at the game's implementation and they are going to add literally every feature we brainstormed and also stuff we haven't". Because if you actually don't intend to do that, then you can instead adopt a pattern of prototyping it in whatever works well for authoring, followed by profiling and hardcoding a fast path as necessary. "Fast from the beginning" is just guessing about the bottlenecks.

And that doesn't mean OOP is definitely good at the authoring task, either. It just happens to be good at kicking the can down the road and letting things work inconsistently, which may be correct in a prototype when you don't know if you're actually shipping that feature, and only poses an issue if you've tied the authoring to the runtime implementation in a deep fashion. Godot doesn't assume this; while it does have hierarchical relationships of objects, it has some boundary points with respect to reuse(scenes and scene instancing) that make the path of least resistance be to make separate authoring and runtime versions of entities, with one spawning the other.

meheleventyone
> This is an example of survivorship bias. How many ambitious game concepts have collapsed under performance/architecture issues that lead to productivity-killing refactoring? Impossible to say, but no doubt many.

Probably less than you think. The games industry knows how to wring performance out of hardware. Data oriented design is common in most game engines where it matters. It’s just it’s not usually the gameplay code that is particularly a bottleneck.

There are also plenty of examples of games where the gameplay layer is a perf concern that not only have been released but were big sellers. For example Factorio and City Skylines. It’s just I’m those examples it makes more sense to worry about data model and access patterns for the actual problem at hand rather than try to generalise it with all the attendant problems that causes. Not least slowing down workflows when you don’t actually need it.

Most game engines are also composition based rather than using much inheritance these days.

Twisol
> This is an example of survivorship bias. How many ambitious game concepts have collapsed under performance/architecture issues that lead to productivity-killing refactoring? Impossible to say, but no doubt many.

I'm reminded a bit of Minecraft, whose infinite and completely mutable voxel world was really novel at the time -- and which was (and maybe still is) the source of a lot of performance woes.

jayd16
>OOP bakes these decisions into the inheritance hierarchy

This is what I don't understand about OOP haters. Inheritance is an optional feature. In fact most ECS frameworks are in OOP languages.

SeanBoocock
Speaking from experience, the hardest part about game development isn’t figuring out how to (efficiently) build something, it’s deciding what to build in the first place. The second hardest problem is getting everyone on board with the answer to that. The third is figuring out how to build the content 1000x to support that. Way, way down the list is the runtime performance for a gameplay system.

True ECS systems - and not frameworks that just have things called “entities” which own things called “components” - are hard to work with, almost by definition (ie you have to be very explicit about data layout and dependencies). They add a lot of friction upfront to solving the important and hard problem(s) while purporting to solve something that isn’t actually an issue in most cases (guess what, your N is likely < 10, modern cpus go brrr, etc). If you are working in a domain where you already know something about the performance and input size characteristics - particle systems are the go to example - then maybe ECS makes sense as a framework. Otherwise, I’d advocate for simpler oop approaches with heavy composition.

danybittel
And if N > 100000, you probably want to use the GPU, ie. a particle system.
arc619
> just have things called “entities” which own things called “components” - are hard to work with, almost by definition (ie you have to be very explicit about data layout and dependencies).

My experience has been completely the opposite to this. In fact being explicit about data layout and dependencies is a hallmark of a OOP rather than ECS.

In compiled languages the dependencies in object hierarchies are fixed at compile time and can only support tree designs, so you have to plan ahead for all possible combinations to even build relationships with OOP, even with composition (because its static).

With ECS everything is decoupled so you can write a system that does X and it affects nothing else.

This leaves you free to design by isolated processes rather than by code structure, and entities naturally do whatever processes their data supports dynamically.

Makes iterating designs incredibly rapid and offers design options that are convoluted and fragile with OOP such as completely changing what an entity does at run time.

For instance you can move the keyboard input component from a player entity to a monster or even something as random as a building and it just works - you didn't have to design for it, you don't even need to change any code. Remove the health component, now the entity is invincible, remove the gravity component and now it can fly, add a homing component and now it seeks a target. All this is trivial and can be done at run time. Want flying flaming lampposts the player can control? Just combine the appropriate components. Need to drastically pivot the design? Vastly less work than OOP - sometimes just a case of changing the data in components or their combination in entities without touching systems. Don't need this flexibility? Still gives you a more modular and less coupled design.

As a nice bonus this flexibility comes with more cache friendly performance than static hierarchies to boot.

SeanBoocock
All of what you describe in terms of data driven entity composition is possible without a true ECS framework. That is what I was referring to and more or less what Unreal or Unity (base, not dots) offer.

ECS is one of the better examples of something that sounds good on paper but in practice, and crucially in production, doesn’t provide the sort of benefits that outweigh the friction it imposes.

There seems to be a myopia online around things like ECS, data oriented programming generally, writing games in C (as opposed to that horrible high level monstrosity C++…), optimization, etc. Those are all fine things in and of themselves (though I’ve never understood the opposition to C++ as anything other than nostalgia), but they are often discussed without being ground in the considerations of building a game. If you want to build a tech demo, great! However, the needs of building a game with hundreds of people, most of whom aren’t engineers, and to a quality/production level that even “simple” things become complicated, demand other things take precedence. I lead a team that facilitates a creative project, not to satisfy my technical desire to have optimal cache or thread utilization in every piece of code. The right tool is the one that gets you closer to the creative goal, and for gameplay code most of the time it probably looks like what Epic or Unity are shipping with their entity frameworks.

EamonnMR
I've played maybe one game with entities in that count range (Planetary Annihilation) and I think you'd need a lot of low level engine work for something like that anyway (since it's doing all sorts of neat stuff with interpolation, weird coordinate systems, networking, etc.)
worldsayshi
After working too long with stateless API:s on the backend and one state container to rule them all react-redux kind of architectures on the front end the OOP code style kind of makes my skin crawl. When I try to learn Unity I find it so hard not to turn my code into spaghetti.

Hearing about ECS gives me hope.

flohofwoe
Unity has always been more "ECS" than "OOP" though (traditional Unity has Entities and Components for composition instead of inheritance, modern Unity moves Component data and logic into Systems for performance).
worldsayshi
Hmm, I thought the ECS parts of Unity is part of the Unity DOTS system, which still seems in an early stage, at least in regards to ecosystem?
ratww
The only major difference (in regards to code organisation) between Unity's old classes and ECS is that in Unity the logic ("Systems") is coupled with the data ("Components") in the same class.

Entities in Unity are already not concrete implementations (probably just a "handler" ID) as far as the user is concerned. This is pretty much like ECS.

flohofwoe
Yeah, kinda. But the term ECS definitely already existed before the "data-oriented revolution" for engines that used components attached to game entities to achieve "feature composition". Not sure what the "S" stood for at the time, probably not "Entities/Components/Systems" (because "Systems" is the new thing that actually matters), maybe simply "Entity-Component System" as in "this is an Entity-Component system".
Jare
I like the suggestion elsewhere in this discussion, to call them "Entity Component architecture" and "Entity Component Systems architecture".

It's just replacing one word with a similar one but makes a world of difference in clarity.

seba_dos1
FWIW there is also a ECS implementation for Godot available: https://github.com/GodotECS/godex
criddell
Would either Godot or O3DE be a good choice for a CAD-type application? It looks like Godot deals well with a scene graph which seems like a good way to organize data for that kind of application.
lqr
Graphics-wise, the assumptions are quite different. Game scenes are a large collection of low-detail objects that are constantly moving and not all visible at once. CAD scenes are a small collection of high-detail objects that don't move except in response to input events.

If the CAD project is big and serious, I would be afraid of eventually hitting some limitation of the game engine that is hard to work around due to such different assumptions.

criddell
Both game engines and CAD applications have some type of level of detail node in their scene graph so that zoomed in items are high fidelity and items further are simplified.
pjmlp
You would want something like OpenInventor instead.

https://www.openinventor.com/

criddell
Is that related to Autodesk's Inventor at all?

I work on an application that uses the geometry kernel from PTC (GRANITE) for modeling and OpenSceneGraph for display. I'm a little worried about OpenSceneGraph because it's 100% OpenGL which feels like it's at the end of it's life and we need to find something built on Vulkan or Direct3D for the future.

pjmlp
Nope, it was born as IRIS Inventor, the actual crown jewel for SGI, when they let IRIS GL turn into OpenGL, they kept it for themselves.

https://web.archive.org/web/20041120092542/http://oss.sgi.co...

None
None
esens
Neither is designed for a CAD engine. CAD uses generally NURBS and a scene graph based around constraints. Game engines are not constraint based but rather about independent behaviour agents interacting using triangle meshes. Quite different.
worldsayshi
Interesting! Is there any game engine or open source engine or library that would support those kinds of code styles?
TaylorAlexander
I desperately want open source CAD to be a thing. I would suppose that Freecad is probably a very good starting point. I don't think the lack of good open source CAD is due to a lack of a decent codebase so much as the fact that good CAD software is a very large project and we have just not directed enough efforts towards it. I am speculating however and may be wrong.
criddell
> I don't think the lack of good open source CAD is due to a lack of a decent codebase

I think the problem is exactly that. A good constructive solid geometry (CSG) is a difficult thing to make and there are no open source alternatives to the ones powering the mainstream CAD packages.

TaylorAlexander
(I have not looked so this is a genuine question)

Is there an actual issue with the freecad codebase? It has always seemed relatively functional.

guywhocodes
It's hard to avoid the segfaults. I've tried to use it many times for simple projects. Some workflows it's every 10min or so, and often you get into corrupted states where you can tell it's about to happen, but of course if you save you risk your files completely.

It's also slow, onshape in my browser beats it at roughly everything.

CamperBob2
Closest thing would be a level editor, which is very much a CSG-based CAD program with roots going back to the Quake 1 generation. It's just not geared towards typical production applications where real objects are being machined.
criddell
Did it have boolean operations like add, subtract, and cut?
CamperBob2
Yes, along with the usual extrusion and (I believe) lofting along a desired path.
worldsayshi
Rather than "just" Open source CAD I would like to see Open Source CAD-like applications. Well, at least in my mind CAD is something kind of specific and carries a lot of design assumptions with it.

I feel there is a lot of cool stuff you can build in the space of building shapes using constraints. Like visual programming languages made to visualize mathematical relationships using geometry.

TaylorAlexander
Interesting. In my case I am specifically talking about mechanical design CAD for engineering. We have a huge need for that in my opinion. Freecad might be the closest thing but I suspect it needs more investment.

However what you’re talking about sounds important as well.

porphyra
For NURBS modelling there is OpenNURBS [1], made by the guys who made Rhinoceros 3D, an excellent NURBS 3D modelling program. However, although Rhino is available on Windows and macOS, it is not available on Linux and the authors seem pretty against making a Linux version. OpenNURBS is only available on Windows.

[1] https://www.rhino3d.com/opennurbs/

animal531
I personally use MoI3d (http://moi3d.com/). It is basically Rhino but cheaper (albeit with less tools and features).

But as an Indie dev it gets the job done for me.

mkishi
That link says O3DE uses EC, not ECS. These are terribly named and often cause confusion, but they are different.

In "Entity Component" systems (think Unity), entities own components that give them data and behavior.

In "Entity Component System" systems (think Unity DOTS), components are just data, and behavior is driven by systems that live outside entities.

They are similar in some aspects and both are radically different than a deep OOP hierarchy, but ECS is quite more hardcore on decoupling. It's been a few years and it's still not unanimous whether adopting Unity DOTS over regular Unity is easy or even worth it, for instance.

Still, Godot isn't very OOP either, working mostly with composition of behaviors.

geokon
Do you have an good references for implementing an ECS? I've only found very high level descriptions but they all are a bit handwavey and avoid the implementation details.

I know Entt is a highly praised library, but I'd be interesting in folding in ECS as a general design pattern in my programming.

https://github.com/skypjack/entt

blarg1
Ah I got excited for a second, I'll stick with ue4 if its only EC
mcphage
How old and how widespread is the “EC” vs “ECS” naming distinction? Both of those used to be called ECS (at least as far as I understand).
badsectoracula
EC predates ECS and goes back to at least 2008 or so.
bmn__
https://news.ycombinator.com/item?id=26292671

ECS was popularised with http://enwp.org/Dark_Engine in 1998. The architectural style probably existed already earlier, but I have no evidence I can point to.

badsectoracula
Are you sure about the Dark Engine bit? I remember comments from people who've seen the code saying that it was an OOP mess with weird macros over C++ features that looked like COM on a bad day, which sounds completely antithetical to what people call ECS nowadays.

Perhaps it was confined to some part of the engine? ECS didn't come out of thin air after all, it is a generalization of practices people already used for things like particles, etc.

Andrex
> In "Entity Component" systems...

> In "Entity Component System" systems...

Something something Douglas Adams.

djur
It's less confusing when written "Entity−Component−System architecture". That is, it's a list of the three concepts -- Entities, Components, and Systems -- that predominate in the architecture.
> The components on the entity define not only it's data but also it's behavior by the set of systems that act on the corresponding components. And you can take these object definitions and inherit them to add additional behavior or change the existing behavior by adding more components to the new definition.

This seems to miss what ECS actually is, unless you're just referring to the old-school way of doing entity components and not the data-oriented way.

Data-oriented ECS way of doing things is to separate state and behaviour. Entity components essentially become structs where their only behaviour is potentially some getter/setter utilities.

Behaviours are then state-less systems (just functions, essentially) which act on a set of components.

For example, a PhysicsUpdateBehaviour might take in a RigidBodyComponent and a HealthComponent to perform a physics update and apply physics/fall based damage.

The main benefit of ECS (imo) isn't even really performance. It makes code in complicated game projects much easier to manage by clarifying the game loop and by making it much more obvious how and when entity state is being modified.

It's the kind of thing that potentially complicates a smaller project, but makes larger more complex projects easier to manage.

This Overwatch GDC talk is the best breakdown/example of data-oriented ECS in a AAA game that I know of: https://www.youtube.com/watch?v=W3aieHjyNvw

meheleventyone
I know what an ECS is. Components are decoupled from systems (not not visa versa) but the actual behavior of an entity is defined by the set of systems that run on the set of components so in that sense the set of components defined what the Entity is including it's behavior. An Entity is defined in terms of it's data and it's data brings along behavior.
Yes but the game is deterministic and trades inputs which are rewound and resimulated. I don’t think the interesting part of rollback net code in fighting games is that it’s usually peer-to-peer. There’s a GDC talk on how it works here:

https://www.youtube.com/watch?v=W3aieHjyNvw

chupasaurus
I know how it works. The only major difference for FPS is that there are multiple inputs inside a frame which have to be precisely timed. All the prediction models are either deceiving for a false reaction or the same "keep doing the previous action".
mold-monkey
What you described is how sensitive a fighting game is. Which need to be 60FPS because moves are made within that limit with startup frames, active frames and move recovery on block vs whiff. The only FPSs that come close to FG levels of reaction/inputs is Quake, Unreal and maybe CSGO.
For anyone curious to know more about usage of ECS in Overwatch, check out this GDC talk from one of the developers: https://youtu.be/W3aieHjyNvw
dividuum
Awesome talk. Thanks for linking.
That's cool, I didn't know that. I've found the presentation: https://www.youtube.com/watch?v=W3aieHjyNvw
This is a next step for my project as I'm trying to figure out how to generalize client side predictions in a sane way.

Basically, I'm happy with my latency (for board games) which I hope to migrate closer to people as more edge compute offerings emerge. However, I'm wondering what the path is to find some of these ideas in more latency sensitive applications.

The explanation for how the net-code behind Overwatch is a good explanation: https://www.youtube.com/watch?v=W3aieHjyNvw

and I'm just trying to figure out how to build the reactive tree in a way to support it sanely.

Fire-Dragon-DoL
Consider that while a videogame runs on 60fps (or more), a board game runs on frame-per-turn. You would be doing what overwatch is doing in a frame, for an entire turn. That's way easier: if a turn is out of sync, revert to the previous one!
juskrey
You don't have to predict. Requests just fall into two categories:

1) Nothing bad can happen if we show some optimistic result before server returns, but server side will end up in different result.

2) Something bad can happen. Accordingly, for (1) we can do optimistic update, for (2) can't

Feb 17, 2021 · milesvp on Functorio
Your comment made me feel compelled to mention a Blizzard talk I came across recently on the ECS (Entity Component System) architecture they used for Overwatch. It looks suspiciously like a function first architecture in that they don't allow mixing of data and functions. I'm not sure how purely functional it is, but it certainly strikes me as the kind of architecture that Carmack would appreciate in dealing with complexities that lead him to a more functional programming style.

This talk is 3 years after release, and includes all the hindsight they gained from that. Also, the parts talking about the netcode are quite amazing, and the precision of their predictors that they attribute to using ECS.

https://www.youtube.com/watch?v=W3aieHjyNvw&feature=youtu.be

fredrikholm
> I'm not sure how purely functional it is

ECS systems overlap functional programming (FP) only in that both are data first.

Purely functional would mean never mutating an existing value, functions only receiving one value and returning another, monadically binding side effects and so on.

To put it bluntly, a non-trivial computer game in pure FP would hog every resource in your system to barely hit single digit frame rates.

(Disclaimer: I love FP, and use it at my day job. It is not fit for games though)

There is a fantastic GDC video about Blizzard's use of ECS in Overwatch and how it made it far easier to understand the system due to all of the interacting subsystems.

https://www.youtube.com/watch?v=W3aieHjyNvw

bitwize
It's funny because a few years ago I read about how the developers of a game from the same studio -- specifically StarCraft -- ran into the exact same problems I did when trying to write a game in the then-common "bag of subclassed game objects framework" in the 90s. To this day I thank the gods that I chose ECS for my latest game because it has made changes, bugfixes, and extensions of functionality so much easier. To say nothing of more data-driven.
It's definitely been around but I think Unity's (never-finishing) ECS + Rust gamedev community's focus on it has really spiked its popularity/interest lately. Otherwise pretty much every recommendation/engine is OOP-based, with a few straggling extensions/libraries for ECS here and there.

No idea about usage in industry though, but it comes up randomly e.g blizzard: https://www.youtube.com/watch?v=W3aieHjyNvw

Entities are a collection of component instances and nothing more. Components in ECS are data-only. Systems in ECS are logic-only.

If you follow this strictly, then you cannot support encapsulation or data-hiding. There is no sole definition of OOP, but it is widely accepted that the ability to do encapsulation, including data-hiding, is a key part of OOP.

Therefore, ECS is not OOP. QED

If you’ve not seen the Overwatch team’s talk in which they discuss ECS, I can highly recommend it as a good resource to learn about ECS: https://youtu.be/W3aieHjyNvw

There may be models commonly used in those languages you mentioned that are similar to ECS, but you seem to be implying that ECS is a form of OOP; it is not.

Even if you implemented OOP using Structs of Arrays, a thread per object, or whatever you like, you cannot strictly conform with ECS’s requirement that “components have no logic” while also strictly conforming with OOP’s requirement that “objects should not know about each others’ internals” (object hierarchy).

pjmlp
ECS is definitly OOP, just not for those that don't bother reading SIGPLAN papers from the 80 and 90's and the multitude of approaches to OOP and the object, prototype or component based variants thereof, and are stuck with the concept that OOP == Smalltalk-80 as they learned C++ OOP from some C with Classes book.

I guess I need to find some time to prove my point, port ECS examples to Objective-C, Eiffel and CLOS, and provide links to some of those papers as well.

A bit more love for ACM and IEEE goes along way in acquired knowledge.

https://youtu.be/W3aieHjyNvw I think this talk on how an ECS actually reduced coupling in the case of Overwatch would be a good concrete real world example to look at. It enabled some architectural benefits for implementing replay cameras or for networking code in their game through actual reduced coupling between input ->commands and commands->simulation.
I think DoD can be ergonomic, actually, if you're doing it just for the architecture reasons vs. the optimizations reasons, to the point that you choose DoD due to them. At least I personally have found that eg. an ECS architecture can lead to separations and structurings of logic code that were helpful, while still defining data in ways that I could just make accessible to tooling and so on.

In this talk on their architecture for Overwatch: https://youtu.be/W3aieHjyNvw (highly recommend) you can see that the wins / concerns they talk about have to do with architecture more than perf. Big insights at 8:00 in the video.

Aug 24, 2020 · nikki93 on Unity Software Inc S-1
That point (keeping interactive rates) is basically one of the most important factors driving the architecture of game engines. I found this talk to be quite a good one regarding architecture for game engines (it's about the ECS in Overwatch): https://www.youtube.com/watch?v=W3aieHjyNvw

I feel like Unity's "entity as a container of components, things are OO'd and there's a lot of polymorphic dispatch / existence checks / branching" is starting to feel out of fashion as of late, and the ECS approach is something folks have come around to.

I've been playing around with such an engine for a side project. Here's a quick video -- https://imgur.com/a/BcnWJha -- you can see what the in-game editor looks like + some of the physics of the game (the game and editor run both in web and natively). I think with the ECS-queries approach the code comes out to be quite ergonomic. For example, I've highlighted the logic that makes the player be obscured by objects in front of them here: https://gist.github.com/nikki93/8cc5d99e45ad74e7f1053dbef287... The game-specific code for the whole game is in that 'main.cc' file and comes out to about 500 lines. The game also includes custom inspector UIs for the 'Sprite' and 'Feet' components that are defined right in that file on line 288-314 and you can see them in the video.

danbolt
> I think with the ECS-queries approach the code comes out to be quite ergonomic.

I tend to agree, and I think it's something that doesn't get promoted enough as an advantage of ECS compared to cache hits and parallelism. When a programmer wants to add a new feature to a game, they can slot their system into the game's tick and avoid stepping on their peer's work as much. They won't need to edit `Entity.cs` or an inheritance tree, and it's much easier to reason about the order of updating game data per frame. It also makes code ownership and code reuse a bit easier to divide up too. I'd take an ECS system even with a performance penalty, as the organizational benefits really add up over time.

nikki93
Glad to see some agreement there. I'm interested in building an ECS-based approach for a UI system at some point. The Yoga layout engine (implements flexbox -- https://github.com/facebook/yoga/tree/master/yoga) seems to actually be pretty amenable to just incorporating as a `Layout` or `Flex` component, then you could have components for platform-specific renderings (eg. `iOSTextInput`, `AndroidTextInput`, `DOMTextInput` in wasm, ...) that could read from cross-platform common components (`TextInput`). A core aspect would also be a `Hierarchy` component that just has a parent entity id and a list of child entity ids (that it keeps in sync properly). Then bind things to JS and allow you to code it from React, while still being able to eg. run an animation thread for some specific animations that just queries and reads/writes the `Layout` and `AnimationSpec`s etc. Interesting talk re: data oriented design for a webby animation engine here actually: https://youtu.be/yy8jQgmhbAU?t=620
Here's an interesting presentation on Overwatch's ECS system, though he doesn't go into great detail in terms of multithreading, he points out how the design makes it easy to identify what parts of the system can be safely run in parallel.

https://www.youtube.com/watch?v=W3aieHjyNvw

The important two points are that the client must react immediately to a user's input, but at the same time the server has to have the authoritative game state.

One way of doing that is that the server runs the authoritative simulation and the clients send input to the server, but the clients also run their own simulations. In some games the client will try to predict what the server will do. If there's a conflict with what the client simulates compared to the server then the client gets rolled back to the server's state. This usually happens when there's a second player that interferes in some way.

Here is a talk by Timothy Ford about Overwatch's netcode (it's really fascinating): https://www.youtube.com/watch?v=W3aieHjyNvw

May 10, 2020 · mtsr on EnTT: Gaming meets Modern C++
Since you generally want to keep a set number of time steps the commonly used data structure for this is a ring buffer. No garbage and all you do is increment the index (with wraparound) every step.

Not a lot of technical details, but this video has a great general overview https://www.youtube.com/watch?v=W3aieHjyNvw

Overwatch allows none of that and seems to have some pretty well-designed netcode. Clients only send their controller inputs and the server has full authority of what actually happens. Blizzard's GDC talk about it is really good if you want an explanation of how to make a game feel responsive and fair without giving clients authority over everything [1].

Ofc this does not eliminate aimbot or wallhacks, but it gets rid of pretty much all other forms of cheating.

[1] https://youtu.be/W3aieHjyNvw?t=1341 (Netcode talk starts at 22:22)

chupasaurus
It does eliminate most of wallhack opportunities, unlike CS:GO/PUBG/CoD:Warzone/Valorant.
throwaway2048
CS:GO does not belong in that category
chupasaurus
Each one from that list could be removed by a certain criteria. By server-client architecture and netcode CS:GO is worse than the others by a few miles, yeah.
throwaway2048
Its really not, it has full server side simulation/verification, PUBG has none and is completely client side for instance.

The only viable hacks in CS:GO are aimbots and extremely limited wall hacking (basically you can see a few "feet" around corners, the server does not send you any other data).

This compares to PUBG where you can press a button and headshot the entire map at once, while flying through the air and spawning guns.

There's plenty of good talks and literature on the subject and why it is applicable to game development, but also more generally.

This talk by Mike Acton (Formerly Insomniac now Unity): https://www.youtube.com/watch?v=rX0ItVEVjHc

I recommend this talk all the time, since it is the one that got me convinced to look into DoD seriously.

Also: More Mike Acton (now at Unity): https://www.youtube.com/watch?v=p65Yt20pw0g

Stoyan Nikolov “OOP Is Dead, Long Live Data-oriented Design”: https://www.youtube.com/watch?v=yy8jQgmhbAU

Overwatch Gameplay Architecture and Netcode (More specifically about ECS): https://www.youtube.com/watch?v=W3aieHjyNvw

The main argument is that you work with data so you should care about data. All a program does is take some input, do something with it, and give you an output. If you structure your program around this mindset, a lot of problems become much simpler. Concurrency is one thing that becomes much simpler to reason about now that you understand how your data is managed and moved around. Realisations that most of the time you have multiple of something and very rarely do you have a single thing. So having a lot of small objects of the same type each doing some work within their deep call-stack, rather than running through an array of them and doing the work you need to do.

I disagree that encapsulation is a brilliant idea _in general_, because it promotes hiding data, and hiding data is not inherently good. There's obviously cases, where there is internally critical, but since all your state is simply tables of data, your program is just choosing to represent that data in some way, which can make it easier to centralize a bug early.

There's obviously pros and cons, but I don't think you should discount the possibility of it being a good idea just because it questions ideas that seem standard.

> running a simulation (what OOP was invented for)

I used to believe that. I no longer do. Among other things, I watched this talk about Overwatch's architecture and it really seems like you have to go against your OO instincts to create larger simulations: https://www.youtube.com/watch?v=W3aieHjyNvw

Mar 28, 2019 · 1 points, 0 comments · submitted by hedgehog
I've been wondering for a long time about how ECS can be cache friendly.

If you look at Overwatch's ECS ( https://youtu.be/W3aieHjyNvw?t=326 ), there are many systems that can read from 10+ different components. For every entity in this system, at least 10 reads with no locality whatsoever are done. That seems crazy slow to me.

skypjack
I saw the video, but they don't go much in details on the actual implementation, so it's hard to say where, how and if things are optimized or not. Moreover, the speaker stresses also on the fact that ECS is used for code organization in most cases and they benefit a lot on this aspect.
cma
Consider instruction cache locality as well. That system will run sequentially running the same code for all entities that need it, and is likely to all stay cached.

Whereas if you tick each entity separately and run all the logic, each new entity tick is following on to so much unique code having run that it is probably starting all over on uncached instruction fetches.

bfrydl
It's ten reads, but each of the ten reads is typically just an index into a big sequential array. Also, when you're reading components, you can run that system in parallel with any other systems that do not write to those components.
meheleventyone
The point of data oriented patterns is to structure data how it is used. So if these lookups were bottlenecks you'd collapse components together if they were always used together.

The other idea is that where there is one access pattern there will be more of the same. So by updating by System you keep as much as possible hot in cache by doing all the similar lookups together. So whilst the first lookup might have ten complete misses the next one probably won't.

At a gameplay level there's a lot of chaos going on and entities are not generally doing things that are easy to organize in a way that avoids cache misses anyway. On top of which you are juggling ease of change with optimization. At which point you just need to be fast enough. I'd also bet most bottlenecks for Overwatch were not in gameplay code.

Mostly though people should be thinking in a data oriented way rather than grabbing an ECS framework and expecting that to magically make things cache efficient.

Here is a talk by Blizzard about Overwatch which uses ECS: https://youtu.be/W3aieHjyNvw
Feb 09, 2019 · 22 points, 1 comments · submitted by fritzy
goldenkey
Though everything works in practice, it seems like this ECS organization in C++ is encumbered with all of these issues, some as simple as issues with new entities occlusion with currently looping iterators. I admire what they did, but it just seems so unpure and not pristine.

Is it just the nature of the area of development..gaming? Or is it just because C++ is pretty much defacto for perf, and no large company is going to rock the boat?

HN Theater is an independent project and is not operated by Y Combinator or any of the video hosting platforms linked to on this site.
~ yaj@
;laksdfhjdhksalkfj more things
yahnd.com ~ Privacy Policy ~
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.