There are other attempts to build a game engine in Rust. In my opinion, what sets Bevy apart is the pace at which they’re developing. Look at the release notes for Bevy 0.4 (https://bevyengine.org/news/bevy-0-4/), released 6 weeks after Bevy 0.3 (https://bevyengine.org/news/bevy-0-3/). They have momentum, plenty of contributors (50+), improving the ergonomics of existing APIs, improving the performance of pieces already performing well.
If I was making a game today, I’d probably pick Unity. A year from now? I’d take a good look at where Bevy is then. Good luck to cart and the other contributors.
I really like Bevy but I think that's a bit optimistic and based on the size of the studio.
Godot is in a much better spot at being the next Unity and it took a long time. It's still not there because of assets availability: you can find assets for anything for cheap on Unity.
For an indie developer with little budget and time to build complex features, it's a life saver.
For a mid-size studio (Embark?), happy to build their own technology, Bevy could be a great starting point, but the feature set is still not there.
As a solo developer trying to build a game, I tried going Bevy / Godot / tons of others and ended up back to Unity: I don't like it and it's a complete disorganised and buggy mess but it gets stuff done incredibly quick.
I didn't pick Unreal Engine because of the 5% cut over 3k. It's a marginally nicer environment to work in but I don't think it's worth the price tag over Unity (free under 100k revenue).
Rust while nice still has to catch up with 30 years ecosystem of tooling.
Many game studios won't bother using it if it doesn't come on the console vendors devkit, just like it happened with C, C++, or middleware like Unreal and Unity.
What they likely mean is that C++ gamedev libraries have been heavily optimized over the course of many years, so while there is no theoretical limitation on Rust's equivalents, polishing them to the same degree is nontrivial and takes time. Bevy is the closest and that is a recent development (last couple of months).
I certainly have nothing against this, but even at the pace they are going it will take a long time before this is anything but just another unnecessary "rewrite it in Rust" project to me. I think Godot engine is a lot more promising for general purpose use.
Half of the example repos don't even have screenshots in their own readmes. It's so frustrating when I come across stuff like this - screenshots are such an important hook to really reel me in.
I just recently started learning bracket-lib (fka rltk), and it's tutorials recommend Legion ECS, but I'm finding the macros and magic of Legion to be less ergonomic than what I've seen from bevy. Is it possible/advisable to use Bevy as a standalone ECS, that doesn't require owning the "main loop"?
Awesome, thanks for confirming! I came across that package, it wasn't clear from the docs if it was intended to be imported on its own -- i'll give it a go!
Gamelisp is also a super cool rust game development project. You expose gamelisp runtimes in different parts of your program, then compile and run it with gamelisp programs going into the various runtimes. Now you can iterate on your gamelisp parts without recompiling.
The documentation is very good(!) and the approach is very interesting imo, iteration times disappear but you can keep all your performance (by moving the logic into rust as you settle on a design).
Bevy currently works on the web with a separate WebGL 2 based renderer. WebGPU is the long term target so that the wgpu based renderer will work cross platform. I’m not sure of the status of single-threaded WebGPU rendering but Bevy will not fully support web likely until this issue [1] is addressed. It is unfortunately not a high priority for the Chrome/Firefox teams so will take some time. You need to be able to render WebGPU to a canvas from a worker before you can achieve multi-threading.
Also note webgl 2.0 is not enabled by default on safari (includes any iOS browser). There is an option to enable buried in the settings, but it’s not recommended to leave it on.
So it’s not really an option if you’re targeting ios.
Rust seems like an odd choice for game development: Given adequate runtime performance and expressiveness, perhaps the most valued quality in a language used for the purpose is minimal turnaround time in the edit-build-test cycle.
Here, Rust is, AFAIK, far behind other languages. C lacks expressiveness, but C++ and C# seem popular for the purpose, and their build time is good. Incremental compilation is sometimes available, potentially avoiding a slow, non-parallelizable link step.
Rust is promoted for security, but I have not heard of that as a criterion for game work, and it seems like the first criterion to be jettisoned vs. any other.
What makes Rust's slow build times tolerable for this use? Has it had more progress in incremental building than I know about?
Bevy has very fast iteration cycles and it has been a core "required" feature since the beginning. With our "fast compiles" config, compiling iterative changes to most of the examples takes less than a second. Changes to the "3d_scene" example compile in ~0.5 seconds on my machine.
Check out our most recent efforts in our last blog post, where we added easy dynamic linking for a massive compile speed boost:
https://bevyengine.org/news/bevy-0-4/
In short: fast compile times in Rust are possible. As long as your core libraries do the "right things" when it comes to design, writing user code can be extremely productive. The compiler has also gotten a lot faster over the last couple of years.
Security is relevant on server code and copy protection mechanisms, however modern game development is composed by multiple skillets, that join efforts across middleware like Unreal.
So I am with you that Rust has a very uphill battle for adoption in any game console devkit.
The Forth community takes this one step further: it's more common to see someone discussing their implementation of the Forth language, than to see someone discussing what they developed in Forth.
I'd bet that most new Forth implementations are done for CPU:s that already have vastly more powerful languages available. So if someone want to get stuff done they would probably rather use a more productive language for that. But if they want to tinker around I'd imagine a Forth implementation would be a pretty fun learning experience. I'm myself implementing a Lisp (MAL) just because it's fun. I'm not really planning on using the implementation for anything though.
Competent Forth developers consistently seem to consider Forth a far more productive language than C. Not something I can comment on personally though, I know C far better than I know Forth.
So they say. But every architecture known to man already has a Forth implementation. So why bother make another when you can get busy doing useful stuff? I would say it's just for the fun of programming a Forth.
Have you considered Godot engine? Godot is free software, so legally you have the right to do basically anything with it that Godot engine's owners do. It's years ahead of the engine in the OP in terms of features+polish, and seems likely to continue being developed for a long time. I'd definitely suggest using Godot unless you really need a specific feature of Unreal engine.
If GP is interested in real time rendering features, they may end up butting against the same wall I do every time I try to use godot for a quick 3d experiment: a lot of features you may want when it comes to rendering have been combined with the swap to vulkan, coming in Godot 4.0, which has been a long time coming, with an alpha this year hopefully, but one of the devs has already joked that it will be delayed until next year.
How much of rendering you need? Are you providing the shaders yourself?
If you only need multi-platform rendering (including Emscripten, and a shader abstraction), have you looked into BGFX, or even Sokol GFX? They provide the bits you need to render. Unity is even using BGFX in its "Tiny" version. Sokol GFX is new but very easy to use.
I believe both have Rust bindings if this is important to you.
I'm not sure using Unreal is a risk. It's used commercially by a lot of companies for much more than gaming. It's also open source. Obviously not written in Rust though, if that's important.
> Wasn't this a big deal when Rust hit version 1.0 [1]?
No. The big deal of Rust 1.0 is that a 6 months old Bevy can compile on the latest version of the compiler. Since new features regularly get added, codebases which use the new features will naturally not work with compiler version predating those features.
It is a concern (as seen with the recent cryptography hubhub), but it's a project-specific concern: projects have to decide on their compiler compatibility range.
Though you could say that it's an ecosystem problem, outside of specific projects I don't think there any sort of badge or way to assert compatibility with specific compiler versions. Since distros are starting to ship rustc (and are unlikely to track the standard mainline), I expect awareness of this issue will grow over time.
They promised improvements in keeping backwards compatibility, i.e. building old code on new rust. No one promised forward compatibility, building new code on old rust.
Yeah ok, makes sense of course. It's still a somewhat strange decision on the project's part. It's basically similar to using C++20 features only six months after the first C++ compilers support C++20. If that's a one-time thing during development of the framework it's probably fine. But if in 5 years the project still reqiures a less than 6-months old compiler version, I'd be worried ;)
Why? The advantage of having a single Rust compiler is that there is almost never any reason to use an old one. There are some cases where I can see that using a pinned compiler version would be important: if you are doing mission-critical embedded or financial programming and need a verified compiler. But none of those apply to game development.
I see having a single compiler instead of multiple competing compilers more as a bug than a feature, at least in the long run. It's fine as long as the language is in "exploration phase", but hopefully we'll see more independent Rust compilers in the future (e.g. https://github.com/Rust-GCC/gccrs)
Whether it’s a bug or a feature is immaterial to the present discussion of what you should do when there’s one implementation. The reasonable thing to do is to upgrade the compiler when a new one comes out. Each upgrade is generally pain free because the team goes to great lengths to ensure backwards compatibility. They compile every single open source code base with the latest release before putting it out.
In that context, I don’t see the issue with Rust codebases depending on the latest compiler. I understand that it’s done differently with C/C++ and that’s fine. I don’t see why both models can’t work.
One significant reason to use an old compiler is if you want to avoid having multiple package managers on your system (i.e. rustup _and_ apt).
The normal philosophy on typical Linux systems is in fact _not_ to require bleeding-edge compiler versions; there’s no “gccup” program. It’s the rust project that is proposing a new and different model.
IMO you shouldn't really ever be using system provided versions of compilers or programming languages. Linux distros are significantly constrained in terms of which language versions they package because they need to use those versions to package packages which rely on those languages. That, along with the fact that most distros only release every 6 months to 2 years means that you generally have quite out of date versions.
It seems that rustup itself is not currently packaged by debian or other linux distros which seems to be a bigger issue. If you could `apt install rustup && rustup install stable` then that seems preferably in pretty much every way to `apt install rust` and getting an old version.
I would add that having multiple package managers on the same system can be a hazard.
For example, NEVER install a Python package globally with pip on a Debian System, it WILL conflict with Debian packages (and you'll be very unhappy and confused on the next apt remove or pip uninstall).
For devs, there's no reason to have to use an old version of Rust, especially given Rust's strong backwards compatibility guarantees. It's not like Rust takes advantage of dynamic linking by having all libraries being compiled with the same compiler.
Part of the reason Rust is still fun is that it hasn’t hit the point yet where everything has to worry about backwards compatibility. Let’s keep it that way as long as possible.
You don’t have to. If you want to depend on other people’s code, they may use new features, which may require a newer compiler. But you are in full control there; you are not forced to upgrade.
(Note also it is the compiler, not a runtime. Big difference when it comes to things like deployments, IMHO.)
"runtime" is a term that has conflicting colloquial and precise definitions.
In a precise sense, any non-assembly language, including C, has a runtime. In practice, this makes the term "runtime" not super useful to many folks, so they mean "virtual machine" or "large, featureful runtime that's required to support critical language features" when they say "runtime."
Rust is the same as C in this regard. It technically has a runtime, but not in the way that many people mean.
For as long as Rust has existed, no-one who is writing rust actually wants to use a compiler version that's any older than the newest. The language keeps adding good stuff in every version. I thought it would calm down a bit after NLL, but now everyone is salivating for const generics, which will land in 1.41... and in a whole lot of versions after that, as they split up the feature into smaller, easier to implement and study chunks. The language simply hasn't reached the level of maturity of C++ where people yawn at the new features that are going to be added.
> Most distributions have an LTS that is supported for 5 to 10 years. You won't get the newest, hottest compiler on those platforms.
Yes, you do, because you won't be using the distribution-supplied compiler because like the entire rest of the rust developer community you are using rustup.
There is a huge community wide discussion about this. Characterizing it as “no-one” completely ignores that some of the most prolific and vocal community members have advocated for expressly supporting older Rusts.
One of the core issues here, imo, is that it is unclear which Rust is the oldest one to be supported. That requires a clarity in understanding the pros and cons of each one, and simply due to there being more releases of rustc, it’s a little less clear which version gets you the most bang for your buck here.
I agree that some of this is a function of the new-ness of the language. I think once (if) we start an LTS program, that will help, and is partially why I desire such a thing. https://rust-lang.github.io/rfcs/2495-min-rust-version.html is an example of a feature we’re adding to help people do this kind of thing. It’s small but it’s a start.
If someone is working in an insane environment then that is his problem and also highly unlikely to be using Rust anyway. Why should library developers care about keeping compatibility with old Rust compiler versions for some arbitrary amount of time?
rustup is installed within the user's home directory. If you can't write to your own home, then what can you do on this device that involves compiling code?
> rustup is installed within the user's home directory. If you can't write to your own home, then what can you do on this device that involves compiling code?
there are plenty of companies when you don't have the right to import any new executable code (coming from "outside") in office computers.
Application was built using Java/SpringBoot, and the CI/CD was based on Jenkins.
We had no control over the version of maven/jdk installed within the Jenkins, and the network policies did not authorize outgoing traffic (so no curling rustup). Only one company repository (based on Nexus) was available.
Basically, we were users of a company provided/constrained platform to build our applications using a curated list of tools that has been audited by another team.
If we wanted to add a dependency not present in the provided repository, it would require time for the audit and integration. Time we did not necessarily had.
Now, with Rust/rustup/Cargo, the company would have provided a specific set of Rust versions and a private crate repository. I doubt that the auditing team would have time to add a new Rust version every week.
If a crate present on the private repository is updated upstream and requires a more recent Rust version, the crate update will be delayed until the Rust version is audited/validated/integrated.
IMHO, this is a very common use case, since companies like to split concerns in different specialized teams.
Easy, using system compilers and home mounted as noexec, quite common in corporate UNIX deployments with IT managed development servers that the devs connect from their workstations.
Anyone developing games with this project is likely to be on Windows, Linux or Mac, on x64 or aarch64. Such developers would likely install Rust with rustup, not with the distro provided one. So yes, any developer that fits this description can rely on the newest, hottest compiler.
Some OS-arch combinations might not have the latest one available. This is an issue for OSes that aren’t Windows, Mac or Linux and architectures that aren’t x64 or aarch64.
GDB, llvm, gcc, IDE, devel packages, etc. My distribution (Fedora) contains latest or prior version of rust, cargo, RLS, and clippy, which are updated as usual.
I was under the impression that Amethyst was not a competitor.
There was a post stating Amethyst was basically in need of a re-architecture that could never be resourced and because Bevy was already based on that “new” architecture it was easier to switch all development effort over.
Certainly that rewrite was huge, and it is currently "mostly complete", but Bevy launching when it did helped stifle a lot of the momentum. However, it was picked back up again in November and is now mostly complete: https://github.com/amethyst/amethyst/issues/2517
From outside at this point, the rewrite looks like a mistake , given the lost momentum and the current state of the project, but maybe when they finally get it out it'll turn out differently in 6 months.
This may come off as snarky, but as long as I've been following Rust and Amethyst the latter seems to always be in some kind of "not quite there yet but it will be after the next rewrite/rearchitecture". Same goes for Conrod, its GUI library.
It seemed like an inevitability that some other library would come along that would move forward a bit quicker.
We've heavily invested in legibility and ergonomics in Bevy. I'd argue that our ECS is top tier in ergonomics and legibility across all engines / languages. Here is a gist of a fully self-contained Bevy App for player movement. Feel free to compare that to _any_ other engine / framework:
Functions are "types" just like everything else in rust. And you can implement traits (which can add methods) on any type. So its just "normal" rust code to add a function call to a function of a certain type.
This enables us to (statically) extract information from the type signature of the function and use it to populate the relevant values using the ECS. We also use this type information to automatically (and safely) parallelize system execution based on what ECS resources are accessed (and if they are mutated).
We do (internally) use macros to implement our IntoSystem trait for all relevant function types, but there are no macros in user-facing code.
Yeah implementing traits for functions is rarely advisable. However in this one very specific case (what amounts to dependency injection) it gives us very nice clarity and ergonomics. I'll take that over the macros everyone else is using in this context, or the expensive "runtime reflection" other languages might use to do the same thing. At least its still "normal" static rust code.
One can do that with extension traits, which offer some kind of extension functions. I guess here a Bevy trait is implemented on `fn (commands: Commands)`
If I was making a game today, I’d probably pick Unity. A year from now? I’d take a good look at where Bevy is then. Good luck to cart and the other contributors.