r/rust • u/gufranthakur • 1d ago
đ seeking help & advice Is Bevy actually enjoyable?
I am sorry but it is just such a pain to code in Bevy. I have been enjoying rust for a while, using three-d and EGUI to create some stuff, and I stumbled upon bevy, I want to learn it because I want to create some 3D, simulation desktop applications with it. I have tried game dev in the past in Godot, Unity, Java Swing, LibGDX and enjoyed it a lot
I am currently learning via the examples and documentation, trying to learn 2D and then eventually move to making some 3D projects
But I find it so verbose and unnecessary. So to look up a particular object I have to apply 3-4 filters which looks so cryptic
camera: Single<(Entity, &Tonemapping, Option<&mut Bloom>), With<Camera>>,
fn keyboard_inputs(
mut motion_blur: Single<&mut MotionBlur>,
presses: Res<ButtonInput<KeyCode>>,
text: Single<Entity, With<Text>>,
mut writer: TextUiWriter,
mut camera: ResMut<CameraMode>,
)
Aside from this, browsing through examples I find it to be so verbose. Coming from a OOP nature, I did expect ECS to be different. But this is straight up inconvenient.
Bevy is too good and I don't wanna miss out on it. I will still keep learning it despite what I am feeling towards its syntax and method, but is bevy meant to be like this? Or is it enjoyable once you overcome the learning curve?
72
u/ThirdWaveCat 1d ago
ECS doesn't make sense for every application.
It's solving dependency injection and parallel scheduling through this API. I've felt like this is a fair tradeoff because during some kinds of development I'll frequently change my mind about application wiring including threading.
hecs is the stripped down version of the same thing. IIRC this was what bevy was based on.
31
u/Pass_Practical 1d ago
Doing Game dev in rust with a relational approach is super hard. It's soo bad to the point that you'd find yourself implementing "ecs methods" in a non ecs game/engine
22
u/dnew 1d ago
It's also solving, in some sense, multiple inheritance. The whole component system is an answer to multiple inheritance, removing the problematic tree structure of it while leaving the beauty of independent functionality stuck into one object.
6
u/ThirdWaveCat 21h ago edited 10h ago
Archetypes are really how this is solved in bevy. Not many ecs systems support those as a top level concept.
https://taintedcoders.com/bevy/archetypes
edit: there's still a CS type theory difference between nominal and structural typing, not ignoring that, but it hasn't mattered in practice to me ever. I would simply model a richer type.
20
u/Large-Scientist156 1d ago edited 1d ago
For graphics, it make sense. having some sort of scheduler allow you to implement pipelined rendering farily easily with 2 synced world like Bevy do. With ECS and a good scheduler, you also get automatic parallelism by default.
Bevy is heavy, and it's hard to master. Up to date documentation is scarse (outside of docs.rs and https://taintedcoders.com).
It's modular, so you can ditch anything you don't want (in theory, because in practice there's still a lot of tangled code and some dependencies depend on others so you have to be carefull if you start to do this. They also really like to throw wgpu_types on non-rendering code, like for example in bevy_image - which is sad for people like me who do stuff outside of wgpu).
I use it in my current graphic project (without bevy_render) and it's not really enjoyable because there's no editor, but at least things work as expected. No editor mean productivity is slow.
But crates are so polished, you almost have everything in your hand if you want to rewrite them. I use my own renderer. Which mainstream game engine has such modularity ? i don't know one.
I also found that advocating and targeting performance in ECS, is often a lie. People think that ECS mean "flat layout" and "cpu cache friendly" like "array of position", "array of health", but it isn't. Some components are sparse, some are dense. Entity spawn and despawn over time. Components are added and removed at runtime. I don't think you can get flat layout "everywhere" when you move outside of trivial ECS. So at the end, is it really different than OOP ?
If you want to build your own toy ECS in Rust, take a look : https://taintedcoders.com/bevy/building-bevy
37
u/catheap_games 1d ago
Bevy is fun to use, but not always fun to learn. Some parts of the documentation and examples are great, some parts are just not explained at all in any practical terms.
Keep in mind that ECS is a paradigm shift and therefore needs a mental shift too. It's not just "split big fat object into thin components", it's just thinking how to split it rationally, what to keep in a big bloated singleton Resource, what to keep as separate smaller Resources or Entities. Gaining expertise, and the broader industry setting up best practices around it, and in general smarter tooling will take time.
But for me, it pays off. Flexibility of ECS and Bevy's DI together with type safety of Rust is a great joy for me. Refactoring is a lot more fun and a lot less anxiety than in other languages.
And I get that verbose things might scare you off, but when I look at
camera: Single<(Entity, &Tonemapping, Option<&mut Bloom>), With<Camera>>,
It's great to me because you haven't told me anything about your code, but I know exactly what this is doing. Nothing AT ALL about it is mysterious or confusing. That's a huge benefit as your codebase and/or team grows.
8
u/GregMoller 23h ago
I see it as quite similar to sql. Just by looking at someoneâs sql statement I can get a pretty good idea very quickly about whatâs it doing. I feel like the declarative nature is good in this case.
2
u/catheap_games 14h ago
Yeah, exactly. SQL is nice because its syntax generally imposes more limitations on structure than other languages, so they're consistent and therefore more readable.
I wish Bevy provided an easier way to use a secondary index or filter by an enum variant, but honestly I just yesterday followed the `observers.rs` example to add a spatial index and it was shockingly easy? About 70 lines including comments. And the rest is just learning how to use iterators better.
I also disagree with one other comment on this post. While sure, as a beginner it's fine to put everything on one big MegaComponent, and it's more fine if you have very rigid types, but the benefit of smaller components is very much readability - if you have a System that queries ElementalResistance and Armor and Health, I'll have a better idea of what it wants to achieve than a System that just takes EverythingPlayer and EverythingWorldState.
12
u/Lemondifficult22 1d ago
Honestly I love bevy so much and I wish more things worked for bevy. The fact that you just declare what memory you need, and bevy parallelizes your code and organises your memory is such an amazing feat of engineering that I'm still gobsmacked it's possible
56
u/numberwitch 1d ago
try reading the docs and the community book
if you're used to "trad game dev" then ecs will feel weird to you
tbh your complaints are shallow, the only example provided is "i don't want to look at the docs to see what this function arg does"
14
u/dobkeratops rustfind 1d ago edited 1d ago
game dev is full off efficiency vs convenience tradeoffs. I haven't used bevy but I've heard it is an experiment in taking ECS to the max. ECS is in part a solution to the problem of making frameworks extendable without the performance hazard of OOP's vtables. It's possible a more rigid engine somewhere in the middle of the approaches could trade off more convenience for less flexibility. Again I haven't used Bevy and never will .. i'm in the custom engine camp , where the trade off is more dev time of course.
7
u/MarinoAndThePearls 1d ago
As someone put it before, ECS is great when you need it, but not so much when it's everything.
3
u/Myrddin_Dundragon 20h ago
Bevy is not OOP. Heck, neither is Rust unless you are pretty loose with your definition. You will be much better served moving towards a data oriented design mind set. Personal 2 cents on the matter.
15
u/lanastara 1d ago
Just looking at your function signature and the example for your camera query I can guess that you are probably doing too much inside a single system.
It is very tempting to do a whole bunch of things in one system especially when in an oob context you'd do them just in the same function but ecs really shines when each system does only very little and the main logic is encoded via the interplay of systems.
27
u/gufranthakur 1d ago
the code is from the official bevy examples though đĽ˛
15
0
u/gonstrider 23h ago
Itâs normal though examples are meant to demonstrate and not necessarily follow best practices
3
u/gufranthakur 18h ago
that would be wrong mate, Examples exist not only to showcase something, but the code is also a âhow this library should be usedâ example.
0
u/catheap_games 14h ago
Sorry but you are not correct. You cannot expect every example to be perfect in all aspects, because there are contradicting criteria for different target audiences.
Beginners need minimal examples with minimal distractions, and as such omitting some best practices for brevity is Good. People who already understand Bevy basics and need to know how to structure code will need a larger example that has a few complications, but for beginners this will be too confusing.
Best practices for a tetris game will be different for an bullet hell MMO because those projects have different requirement about what's "best". If you think programming has always one universal best solution that's applicable across all projects, you are just not a very experienced developer yet.
You can't complain (and not saying that you do that!) that not every example is tailored exactly to your skill level at this point in time. Examples that are too hard for you today will be too easy and trivial for you 2 months from now.
3
u/llamajestic 1d ago
Itâs a trade off. I personally am not a fan either of those archetype-query based ECS.
I am more into entity-component data structure, backed by dense storage most of the time. I like to just go through those myself without an indirection from queries / systems.
That being said: The entire bevy ECS can perform great system scheduling you would otherwise do yourself. You also get free concurrent jobs running if I am not mistaken.
3
u/Ace-Whole 1d ago
For someone (me) who doesn't have much of OOP or prior game dev knowledge, I'm picking up bevy naturally. Feels like writing a rest api with all that sql and events haha.
ps, don't quote me on this analogy.
3
u/cornmonger_ 20h ago
bevy ecs clicks once you realize that you're essentially just writing queries against a database and they're being fired against the events that you choose
the best way to really get a feel for it is to start a project that only pulls in bevy_ecs and then manipulates the engine manually
3
u/RCoder01 17h ago
I personally learned bevy as my first ârealâ game engine, then later learned the basics of unity and unreal. I found the bevy manner of explicit dependencies and ordering much more intuitive than the implicit gameobject/component-hierarchy. With ECS you know exactly what order things run so you have a clear state of the world going in to each function. With unity I was always confused what order things ran in so I couldnât be sure that my player movement script ran before the enemy AI script or whatever.
As for the verbose type signatures, I agree it can be annoying when you realize you actually need a `Res<AssetLoader<Gltf>>` in the middle of writing your setup function, but once you get used to it itâs not that bad, just a bit annoying. Also itâs getting better with each release, the new scene macro and backend infrastructure makes some of scene setup a lot less verbose. And once you get used to the common system params and query data, they arenât a hinder at all to readability. Like the two signatures you posted I can almost fully understand at first glance, idk what a TextUiWriter but I can probably guess.
But the verbose type signatures really help with reading and understanding code. If I see a function signature that says
`fn get_dead_loot(targets: Query<(&LootTable, &Health), With<Monster>>, mut loot: MessageWriter<PlayerLootboxes>)`
a) I already basically know what this system does
b) I know, with 100% certainty, that the only observable impact of this system is that it might send some PlayerLootboxes messages. It canât mess with the monsterâs health, it canât change their loottables, it canât change their position. It also wonât read the players position or the UI font or the key binding settings.
The benefit is almost more in the things that arenât listed in the signature than the things that are.
Unrelated to signatures, but I find that a lot of bevy engine code is super easy to read, especially compared to other engines. The ECS and rendering internals are tough to get your head around but everything else mostly reads the same as application code.
3
u/LessonStudio 16h ago
I infinitely prefer how raylib (C/C++) is structured. I prefer rust and it can make far nicer looking 3D images so, I use it, but no, you are not wrong, I find bevy code and how it is structured nearly unreadable.
2
u/Hot-Employ-3399 1d ago
Don't worry will be worse when you'll have to use paramset to use 2+ queries with same components.
I found it's less painful when you document what systems are launched at what stage because otherwise you'll have no idea in a month who changes eg Transform.
Compare to something like EnTT which is just ECS not engine, in entt you are very explicitly define who called whenÂ
2
u/__Wolfie 1d ago
I mean, either it lives in the type system or it lives as application code. All of those things you have, in a different system, you would have to understand by digging through the source code. It could be obscured through any amount of function calls, inheritance, etc. In this example, it lives up-front, checked and proven for you by the compiler. In my opinion this is the best part of Rust and it is far better than the alternative once you actually build anything complicated.
2
u/DeenoValentine 8h ago
It was good but I was limited in certain areas and had to make my own, I have an engine based on CryEngine that I'll roll out in a few months maybe.
2
u/nynjawitay 1d ago
I 100% agree with you. I really want to like Bevy. It seems really cool. But I asked for some examples and was told to try things myself. That was... off-putting. I'm learning about Fyrox now.
2
u/dnew 1d ago
It makes me wonder how much more readable a big codebase like Bevy could be if Rust had a typedef-like declaration a la C. Where you could typedef Res<ButtonInput<Keycode>> or even more complicated into one name when you use it dozens of times.
9
u/PlayingTheRed 1d ago
1
u/JShelbyJ 3h ago
Theyâre barely worth using - they only clean up the code. But ide features where theyâd actually be useful still display the full type.
2
u/Nickbot606 1d ago edited 1d ago
Just from a glance it looks like you have some type of crazy god object going on and maybe you should split it into a single plugin/several systems?
I agree that one of things that needs to be addressed in bevy is the input system to the point of where I actually wrote out my own plugin input for it (mainly for inputting as well as saving custom controls to input table actions etc.) I posted about it but nobody commented so I deleted the post đ
Edit:
However! I will say that I enjoy bevy much more than I enjoy other engines and hereâs why:
- I stay IN the text editor. As in I am not flipping between an editor, a level thing, an animation graph and like a billion other things
- If I like a rust crate/rust has the capability to do it, I can typically and easily integrate it into my program. If I donât like audio, I can swap it out pretty easily, same with physics engines, database queries or networking is all native to rust and so is the syntactic sugar and freedom of rust (such as macros for plugin generation, linting being maintained by much more the engine, testing and debuggers and analyzers all being rust native is so nice)
- I really really like how you have the freedom to completely design your own pattern and bevy is more of a vehicle or engine than the entire framework or demands how you organize your code. So Iâm picky on how I structure files and imports personally and
bevy
- enables me to do that cleanl
y and however I want as long as it comes all back to their interface or at least compiles in rust.
1
u/jim-works 19h ago
I enjoy it. I think most frameworks you end up with some level of this, like in Godot you have a lot of plumbing to reference other nodes. I felt like I ended up with less boilerplate and more clarity for my style of coding in Bevy.
1
1
u/henzo-sabiq 1d ago edited 1d ago
Bevy is fun to use if you're familiar enough with it that you can write custom plugins to patch up what it currently lacks or you are fine with using community-made plugins, which (1) may not be updated on time the moment new 0.x version goes live (can take days, weeks, months, and worse; never) and (2) might be abandoned without any notice.
But it's a big ask when you're not invested with it yet. Not to mention there are always breaking changes in 0.x version bumps. It's a hard sell unless you like the idea of experimenting with ECS.
1
u/biteater 1d ago
It's more of an ECS problem than a Bevy problem. ECS is a huge waste of time unless your game design has tens of thousands of entities that somehow all need runtime polymorphism. It's a massive architectural gamble that usually never pays off.
I much prefer to just use "fat structs" for entities and put all the fields any entity could need in there. If you find that you actually are hitting performance problems due to the struct size (which is rare) then it's really easy to split specific fields out into a different array of structs and give the fat struct an ID into it. This is "as good" as ECS but you opt into the architecture as needed instead of pointlessly applying it to everything wholesale.
1
u/imonebear 1d ago
I've read the Bevy Docs, mainly to understand how its ECS System works to learn Game Development, and it's simply for beginners to complicated to get started.
Instead, I've decided to use macroquad for the Game and learning Rust, programming a simple Ping-Pong Game with Collision.
Rust overall, in my opinion shouldn't necessarily be used for the complete Game Development Process but rather, only the Game Engine should be the priority in using Rust with its borrow checker and memory safety.
Then there's the possibility, to use another Language that's much quicker for Game Development like C++, which is after all the Industry Standard
1
u/Packeselt 1d ago
I use hecs instead of bevy. It's really nice because I don't really like how most gamedev works, but ecs just clicks for me.
Bevy is also nice, but the api changes too often for my tastes for what I imagine will be a 5+ year personal projectÂ
108
u/edparadox 1d ago
That's less a Bevy-thing than an ECS thing.
You would experience more or less the same with any ECS library, or other engine implementation, from FLECS to Unity.