ecs: ECS research #127
Labels
No labels
CI
all
basisu
blog
bug
build
contributor-friendly
core
correctness
deferred
dev
direct3d-headers
docs
driver-os-issue
duplicate
dxcompiler
editor
examples
experiment
feature-idea
feedback
flac
freetype
gamemode
gkurve
glfw
gpu
gpu-dawn
harfbuzz
help welcome
in-progress
infrastructure
invalid
libmach
linux-audio-headers
long-term
mach
mach.gfx
mach.math
mach.physics
mach.testing
model3d
needs-triage
object
opengl-headers
opus
os/linux
os/macos
os/wasm
os/windows
package-manager
priority
proposal
proposal-accepted
question
roadmap
slipped
stability
sysaudio
sysgpu
sysjs
validating-fix
vulkan-zig-generated
wayland-headers
website
wontfix
wrench
www
x11-headers
xcode-frameworks
zig-update
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
hexops/mach#127
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The point of this issue is to collect material / research the best way to write an ECS in Zig leveraging DOD and unique language features like comptime. If anyone has thoughts, please do chime in!
Things I need to look into more / form opinions about:
kbm:
prime31:
slimsag:
kbm:
Bitron:
prime31: "you can get almost exactly that with Flecs too 😉"
people I might be able to run ideas by later:
Exciting stuff. I will say, I wrote a pretty short and shitty "Entity Manager/Registry" data structure, and it was really painless, leveraging
std.MultiArrayList(no benchmarks on it or anything, just an educational experiment to understand it better).One of the things I've understood from reading about ECS, in particular EnTT, is that it's at least similar on a surface level to making a hash map, in the sense that the design and implementation are all based on the balance in trade-offs between memory and speed you want, and that it's nigh impossible to make completely general-purpose ECS software, since it should always cater to the specific problem, unless you heavily leverage a lot of compile-time configuration in respect to those details (which you also have to answer, to what degree do you make that configurable before it becomes a complete mess?).
Whatever the case, looking forward to see Mach come up with something like this, you bet I'll be using it as soon as it's usable. And hopefully I'll be able to learn from more while seeing it progress.
Could you share your
std.MultiArrayListstuff? I'd be curious to take a look (even if it was just an experiment / bad code / etc)Agreed, that is my (uninformed) opinion currently as well.
I think that Zig's comptime can give us some nice ways to express this without getting too far into the weeds. That's my hope, at least. Will see how this pans out as I learn more about the constraints of ECS.
Sure thing, though I'm not sure how readable it is, or if all of the intentions are clear enough to discern; I didn't add many (any?) comments, since like I said, it was purely exploratory: https://github.com/InKryption/small-zig-ecs/blob/main/src/main.zig
Edit: also just noticed, I haven't updated it in a while, so it won't compile without a few tweaks (the Allocgate change e.g.).
Absolutely; it is just my personal opinion that overall, if push comes to shove, over-engineering should be avoided, since it would be better to have a simple, drop-in ECS that can be switched out for a better-suited, personalized system in the future of any project that happens to use Mach (that isn't to say to compromise on speed or efficiency though, those are obviously still important).
I used EnTT in one of my projects for quite some time, but stripped it out in favor of a boring hashmap as I found myself battling its semantics more and more. In particular, managing entity lifecycle was far more cumbersome than the value I as getting. I ran into concurrency issues as well. I also needed reverse look ups so I had my own maps of what entt was tracking...
so the summary would be, I needed:
I ended up just stripping it all out in favor of a trivial set of concurrent hashmaps and an allocator:
and life was so much simpler thereafter.
@meshula Very interesting. How'd you manage concurrency and entity <-> component relations after doing that?
Can you elaborate on what "simple treatment of null entities" and "simple semantics" meant?
concurrency.
I made a MPSC transactional queue, serviced at game loop frequency, but on its own thread. entity creation and deletion is managed via the queue's service routine.
the entity maps are treated as const outside of the transactional queue, any lookups return a locked referent object that guarantees that the fetched component and entity id stay alive until you release it. If a deletion is requested simultaneously, the service queue puts it into a destruction list until outstanding referents are released.
simple semantics.
entity management is done via a provider (which contains the transactional queue)
const references via a referent lock. The component and its data are not const, but its participation in the provider is const if you see what I mean.
entities and components and the ECS are not bound via a type system.
null entities.
* which I solved in EnTT by making sentinel entities. It always felt very heavyweight, and fragile, because it meant that I had to extremely diligent about assigning the sentinels. EnTT gets quite unhappy with invalid queries and reports its unhappiness in fabulous C++ template style at compile time, or at runtime, with similarly convoluted callstacks.
I worked with EnTT for a few years and can say all of it can be dealt with, and you learn how to think about it. But in the end, I felt the juice wasn't worth the squeeze, as it were, and came up with a much simpler pattern that makes me much happier. And concurrency became a deal breaker.
entt issue 470.
Really appreciate that write-up!
interesting resource: https://github.com/SanderMertens/ecs-faq/blob/master/README.md
http://entity-systems.wikidot.com
In case it's useful.
I don't know a whole lot about ECS, so it's probably not the fastest thing in the world, but maybe it can help with inspiration :)
Much appreciated @AliChraghi and @silversquirl !
Thought: One potentially large deciding factor in API design here may be how effectively the ECS, and what it would even look like to have the ECS, integrate with a GUI editor / visualizer of sorts.
Looking at Bevy and Flecs, one truly striking thing to me is just how pervasive and complex their ECS systems are. When looking at them, I find it hard to not draw similarities between React in the earlier days (with extensive lifecycle hooks, etc.)
I'm not sure one could adopt ever adopt portions of these systems, they do seem like something you need to buy into 100%. I wonder if there is an opportunity for a simpler, but obviously more "limited", approach.
Just an observation, still a lot here I don't feel confident about.
Bevy
Bevy's ECS ultimately seems to include the following key concepts:
Flecs
Flecs seems perhaps more complex, their docs have this interesting diagram:
I'll close this issue for now since it's served it's purpose (a collection of people for me to chat with, things to research, etc.)
I sent a very very early stages implementation as well: https://github.com/hexops/mach/pull/156
The concepts are much older than twenty years; worth noting in a research thread.
https://www.chrishecker.com/images/6/6f/ObjSys.ppt <- talk by Doug Church about the "Object System" (ECS) in Thief (1998).
Scott Bilas’ Dungeon Siege paper/article that (around 2002). https://www.gamedevs.org/uploads/data-driven-game-object-system.pdf
Sims used a variant. After 2000, they spread rapidly and became endemic through the industry. Diablo 3 used ECS. Star Wars the Force Unleashed used it (Ronin Engine).
@meshula I appreciate that info a ton! I was aware of some but definitely not most of those so quite appreciated :) I'll update my blog post to link to your message as well so others know
Tim Fords GDC talk about ECS in Overwatch, also how their netcode works to appear zero latency
https://www.gdcvault.com/play/1024001/-Overwatch-Gameplay-Architecture-and
Other ECS stuff I bookmarked
https://github.com/skypjack/entt/wiki
https://skypjack.github.io/entt/md_docs_md_entity.html
https://gist.github.com/dakom/82551fff5d2b843cbe1601bbaff2acbf <- overview of how sparse-array backed ECS systems work
(I've spent so much time over so many years banging my head against a wall trying to get some version of open GL working, to be able to just download and build is like having the heavens open up with trumpets and blinding light pouring out. Thanks)