Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Interactive ECS Systems/Component Explorer for Cities: Skylines 2 (captain-of-coit.github.io)
95 points by CaptainOfCoit on Dec 19, 2023 | hide | past | favorite | 42 comments
Hello Hacker News! Long time reader but first time poster here...

Recently I've been diving into doing mods for Cities: Skylines 2, which been very interesting as it's one of the first games that is using ECS and that I also have a deep interest into. I've mainly used ECS via Bevy before, but this time it's Unity, but many things still work the same way.

In order to help myself and other modders to navigate the ECS Systems and Components from the decompiled code, I created this interactive D3 graph.

You can click on nodes to "navigate" to that system/component, and once you're zoomed in a particular System/Component, you get a sidebar with more details. Ctrl+click also removes nodes in case you want to temporarily filter something.

This is, in short, how it works:

1. A C# program extracts information from decompiled C# code: https://github.com/Captain-Of-Coit/cs2-ecs-explorer/blob/mas...

2. The program outputs that info as JSON: https://github.com/Captain-Of-Coit/cs2-ecs-explorer/blob/mas...

3. Render with D3.js: https://github.com/Captain-Of-Coit/cs2-ecs-explorer/blob/mas...

Basically it helps people to navigate the Systems and Components references for the game.

If you're feeling brave, you can also browse the full graph which has something like ~700 nodes and ~1200 links: https://captain-of-coit.github.io/cs2-ecs-explorer/ (it'll take a while to first load)

A big problem was to figure out how to make the D3 not too messy when there are large graphs, and I don't think I've succeeded very well with this, but everything I tried (link distance based on how many connections, clustering based on namespaces and so on) made it even worse.

Happy to hear what you think and what I could do better.



As a game dev, I'm starting to feel like ECS isn't the right paradigm. Seeing this 700 nodes graph with all the dependencies screams technical debt and domino effect (changing one small system would impact a lot of other ones).

Not sure if there's anything better right now, but seeing everyone copy what Unity did feels like there isn't a ton of innovation in how to build gameplay systems. Lots of engines are being made but not many games come out of it...


> Seeing this 700 nodes graph with all the dependencies screams technical debt and domino effect

Imagine all the various features of the game, it's a city simulation game that currently scales up to a population about 1 million before even 32-core CPUs start to suffer.

You'd have a large code base creating this, no matter the approach.

The game also relies a lot on modding to add additional content from the community. This used to be a big hassle when the first game relied a lot on inheritance. Mods broke each other frequently.

With ECS and this (relatively) decoupled design, modding becomes a lot easier as it almost provides hooks out-of-the-box for you to add your own functionality.

> Not sure if there's anything better right now, but seeing everyone copy what Unity did feels like there isn't a ton of innovation in how to build gameplay systems

ECS isn't really a Unity innovation at all, it has existed for longer than Unity Engine.

Personally, even if ECS had similar performance as the more traditional approaches, I'd still use ECS for my own games as it's just easier to write and reason about a decoupled ECS design, compared to the alternatives.

But then I've mostly used ECS via Bevy, rather than Unity ECS, maybe Unity ECS is a bit more verbose and gets in your way, compared to Bevy ECS.


700 nodes with random interdependencies is better than 700000 objects with random interdependencies though ;)

PS: I'm kinda surprised that a shipped Unity game contains that much human-readable information for reverse engineering. Is there no symbol stripping in .NET?


> PS: I'm kinda surprised that a shipped Unity game contains that much human-readable information for reverse engineering. Is there no symbol stripping in .NET?

I'm pretty sure Colossal Order (the developers of the game) purposefully makes the game easier to decompile (or at least doesn't employ methods to make it harder) as modding is a large part of the game's community. They want it to be easy to mod.


From my experience (both writing games and reading released/leak code) it is usually 70000 objects of well intentioned code and then one hundred thousand lines file player.cpp with all the spaghetti logic added just before deadline.

I've experimented with ECS before and it allows for much nicer decoupling.


> changing one small system would impact a lot of other ones

This is a misunderstanding.

_Components_ don't depend on each other, nor do they (or should they) access each other, because they don't contain any logic. _Systems_ access components.


This graph is also showing system-system dependencies as well as system-component dependencies. I'm assuming that the system-system dependencies are ordering related which implies the dependent systems depend on the results of the previous system either explicitly or more annoyingly implicitly. That's not a bad thing or necessarily avoidable because a lot of things are dependent in games/simulations. If you look at the big graph there are a couple of core systems that must execute first that are probably setting things up for the next tick and then very quickly many fewer dependencies except for core functionality like triggers and pathfinding.

One of the nice things about being able to graph this dependency tree at all is that it means execution can be parallelized easily as long as there aren't too many undiscovered implicit dependencies.

Similarly components don't depend on one another but many systems depend on components so changing those often isn't free either.


> (changing one small system would impact a lot of other ones)

Would you not expect that in a sim game though? I mean, why would you have a nice tree when everything interacts with almost everything?


Of course, but their use of the ECS seems excessive. I'd have expected a few big systems for each area of the game, clicking on Game.Simulation.AdjustElectricityConsumptionSystem for example reveals quite a lot of things that could be within one system. I bet the current design passes and queries data all over the place, very redundantly.


I assume they've split it out so much to better allow smaller systems over larger ones. In theory this should allow better access patterns, for instance for the electricity, the AdjustElectricityConsumptionSystem has to consider each building and the information about it, but the ElectricityFlowSystem only has to consider the edges for electricity flow. This means the ElectricityFlowSystem can be access only the data it needs and in theory allows for better code cache efficiency (since the loops are tighter and more focused than they would be if they were all in one).


> I assume they've split it out so much to better allow smaller systems over larger ones. In theory this should allow better access patterns

Not only that, but modding becomes easier as well, and modding is a big part of the game.

If all the electricity stuff was jammed into just one System, it would be harder to modify just some parts of it while remaining compatible with other mods modifying other parts.

Instead, Systems are broken down into relevant parts so modders can add easier to it or replace whole Systems, without replacing ALL electricity code.


Splitting things this way is also handy because you can avoid branches, rather than one big loop with lots of conditional branching you have many loops one for each set of elements represented by a branch. Except rather than having to untangle and manage that yourself the granular systems approach make it a more natural way to implement things.

Although probably once you're at that stage of optimizing gameplay code it's also probably time to write something specific for the problem rather than trying to fit it into a general purpose framework.


One of the main benefits of doing things with an ECS is composition though so you'd expect more granularity than you'd get in other modular approaches which is of course a tradeoff in some respects.


> I bet the current design passes and queries data all over the place, very redundantly

That's not how ECS works. A system has one or more queries that provide it direct access to the data. There's no passing around of queries or data.


I agree, surely some sparse, distributed representation (that also factors in level of detail) is what will be needed for simulations with truely mind boggling numbers of agents. You’re hitting into a hard physics problem that’s also hitting against the limits of our current models.


This is ECS Done Wrong to be fair, one imagines it'd run even worse with another design.


> This is ECS Done Wrong to be fair

How so? Not sure I love the approach of saying something is "Done Wrong" without pointing to something specific that gives you that impression.


Judging by the system & component names this looks to be pretty well designed tbh. There are a lot of systems for sure, but considering this is a city simulator that's kind of expected.


On the flip side, look at all the systems with no dependencies on the left!


> it's one of the first games that is using ECS

what do you mean by this?


Another (flagged/dead now) comment also asked this. It's helpful to continue reading that line until the end of it.

> > it's one of the first games that is using ECS and that I also have a deep interest into

> Both, at the same time :)

> ECS probably been around since at least early 2000s if not even in the 90s.

https://news.ycombinator.com/item?id=38703926

I guess if at least two people asked this question, my initial description wasn't clear enough that it was supposed to be a AND statement.


> it's one of the first games that is using ECS and that I also have a deep interest into

FWIW, I did read to the end of the line, but I parsed that as two separate assertions (with “and that” being a means to introduce the second assertion):

1) it is one of the first games using ECS

2) that you also have an interest in it

Rather than the intersection of:

1) the set of games using ECS

2) the set of games that you have an interest in

Or, expressed another way, it’s this (how I read it):

(it's one of the first games that is using ECS) and that (I also have a deep interest into)

Vs

it's one of the first games that: (is using ECS) and that (I also have a deep interest into)

I suppose I would have written this:

It’s one of the first games using ECS which I have also had an interest in.

I’m fairly certain I’ve almost always seen something like “[of] which” to introduce another qualifier, whereas “and” almost always introduces a new statement that stands on its own (the exception being in more formal contexts where there’s a sentence structured along the lines of “consider such [insert class of objects here] which are both: [this] and [that]”).

I think it’s the “and that” which threw me (and others here who misread you) off.


Thanks!


I had the same question.

"The Entity Component System (ECS) is the core of the Unity Data-Oriented Tech Stack. As the name indicates, ECS has three principal parts:

Entities — the entities, or things, that populate your game or program.

Components — the data associated with your entities, but organized by the data itself rather than by entity. (This difference in organization is one of the key differences between an object-oriented and a data-oriented design.)

Systems — the logic that transforms the component data from its current state to its next state— for example, a system might update the positions of all moving entities by their velocity times the time interval since the previous frame"

From https://docs.unity3d.com/Packages/com.unity.entities@0.17/ma...


It uses Unity's ECS implementation (entity component system), part of DOTS (data oriented stack) https://unity.com/dots


...and that I also have a deep interest into.


Anyone know if mods in general work when running CS2 inside Steam on Linux? It's kinda hard to search for since there are a lot of Cities: Skyline results mixed in.


There are people who've had success running mods with CS2 on Linux + Steam. Give it a try, and if it doesn't work, jump into the Discord (linked in my profile) and I'm sure we could help you.


This is amazing


Thank you for the kind words! :)


What is ECS?



Slightly off topic, but does anyone know what the status is of Unity's patent on ECS? I remember this thread [0] from a few years ago, and it looks like the patent is still valid [1], but I still see ECS all over the place outside of Unity contexts. Is Unity just not interested in enforcing the patent? Do they know they'd lose if they tried? Or am I missing a recent development?

[0] https://news.ycombinator.com/item?id=28447672

[1] https://patents.google.com/patent/US10599560B2/en


The patent abstract indicates it's not a patent on ECS, but a patent on methods to improve performance with ECS systems. The patent was filed in 2018, which is far after ECS was already in commercial use.


Here's cart's analysis: https://i.imgur.com/Kmokcmq.png

Cart is the creator of Bevy (ECS engine in Rust) and Sander is the creator of Flecs (ECS engine in C)

Assume they lose if they try to enforce it, but don't know of any attempts yet.


So, uh, am I reading that right? One part is “use array of structs for ECS” and the other is “use struct of arrays for ECS”? Really?


Yeah the optimization is similar to the realization that array-of-structs can be the faster memory layout if you use all/most of the members of the struct. So you organize memory by archetype rather than keeping the components separately.


As sibling points out, it's about a specific way of optimizing an ECS style program. That's typical corporate software patent stuff - building a moat with patents that aren't inventive. It's like firing a shotgun into the solution space to create off-limits areas and impede newcomers.


The Wikipedia article provides a broad overview, while this FAQ offers a more systematic exploration: https://github.com/SanderMertens/ecs-faq


[flagged]


> it's one of the first games that is using ECS and that I also have a deep interest into

Both, at the same time :)

ECS probably been around since at least early 2000s if not even in the 90s.

Edit: Wikipedia puts Thief as the "pioneer" of ECS:

> In 1998, Thief: The Dark Project pioneered an ECS. (https://dev.to/ovid/the-unknown-design-pattern-1l64) The engine was later used for its sequel, as well and System Shock 2.


I think it's one of the first games heavily using Unity DOTS, which probably also explains its launch troubles.


Unity's new ECS system I assume, not ECS as a general architecture




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: