That's a good article. He's right about many things.
I've been writing a metaverse client in Rust for several years now. Works with Second Life and Open Simulator servers. Here's some video.[1] It's about 45,000 lines of safe Rust.
Notes:
* There are very few people doing serious 3D game work in Rust. There's Veloren, and my stuff, and maybe a few others. No big, popular titles. I'd expected some AAA title to be written in Rust by now. That hasn't happened, and it's probably not going to happen, for the reasons the author gives.
* He's right about the pain of refactoring and the difficulties of interconnecting different parts of the program. It's quite common for some change to require extensive plumbing work. If the client that talks to the servers needs to talk to the 2D GUI, it has to queue an event.
* The rendering situation is almost adequate, but the stack isn't finished and reliable yet. The 2D GUI systems are weak and require too much code per dialog box.
* I tend to agree about the "async contamination" problem. The "async" system is optimized for someone who needs to run a very large web server, with a huge number of clients sending in requests. I've been pushing back against it creeping into areas that don't really need it.
* I have less trouble with compile times than he does, because the metaverse client has no built-in "gameplay". A metaverse client is more like a 3D web browser than a game.
All the objects and their behaviors come from the server.
I can edit my part of the world from inside the live world. If the color or behavior or model of something needs to be changed, that's not something that requires a client recompile.
The people using C# and Unity on the same problem are making much faster progress.
> I'd expected some AAA title to be written in Rust by now.
I'm disinclined to believe that any AAA game will be written in Rust (one is free to insert "because Rust's gamedev ecosystem is immature" or "because AAA game development is increasingly conservative and risk-averse" at their discretion), yet I'm curious what led you to believe this. C++ became available in 1985, and didn't become popular for gamedev until the turn of the millenium, in the wake of Quake 3 (buoyed by the new features of C++98).
I really hope that C++ evolves with gamedev and they become more and more symbiotic.
Maybe adoption of rust by gamedev community isn't the best thing to wish to happen to language. Maybe it is better to let other crowd to steer evolution of rust, letting system programming and gamedev drift apart
I sometimes wonder if the problem with rust is that we have not yet had a major set of projects which drive solutions to common dev problems.
Go had google driving adoption, which in turn drove open source efforts. The language had to remain grounded to not interfere with the doing of building back-end services.
Rust had mozilla/servo which was ultimately unsuccessful. While there are more than a few companies uinf rust for small projects with tough performance guarantees - I haven't seen the “we manage 1-10 MM sloc of complex code using rust” type projects.
> and didn't become popular for gamedev until the turn of the millenium
Wasn't this also because Microsoft had terrible support for C?
Since the mid-90's, a number of gamedevs moved to C++ but were unhappy with the results.. how OOP works, exception handling, the STL, etc.
My understanding is.. by late 90's.. many game developers, despite using C++, we still coding more inline with C programming than (proper) C++.
Mostly C code but using some features of C++ like, functions inside a struct, or using namespaces, that did not sacrifice compilation and runtime speed.
Yeah, gaming industry has become mature enough to build up its own inertia so it will take some time for new technologies to take off. C# has become a mainstream gamedev language thanks to Unity, but this also took more than a decade.
Comparing the time it takes for a prog language to spread from the 80s to today is a bad vantage point. Stuff took much longer to bake back then -- but even so the point is moot, as other commentors pointed out, it took off roughly the same amount of time between 2015 and today.
The concept of AAA games didn't even exist back in 1985, very few people were developing games at that era, and even fewer were writing "complex" games that would need C++.
The SNES came on 1990 and even then it had it's own architecture and most games were written in pure assembly. The PlayStation had a MIPS CPU and was one of the first to popularize 3D graphics, the biggest complexity leap.
I believe your are seeing causation were only correlation should be given. C++ and more complex OOP languages just joined the scene when the games themselves became complex, because of hardware and market natural evolution
Many tried c++ in early 90s, but wasnt it too slow/memory intensive? You had to implement lots of inline c/assembly to have a bit of performance. Nowadays everything is heavily optimized, but back then not.
> I'd expected some AAA title to be written in Rust by now.
Why? Those kinds of game engines are enormous amounts of code, and there's little incentive to rewrite.
I do strongly disagree that we aren't ever going to see large-scale game development in Rust; it just takes time. Whether games adopt an engine is largely about that engine's maturity rather than anything about the language. Bevy is quite young; 0.13 doesn't even have support for animation blending yet (I landed that for 0.14).
It was a few years back that the question came up to the developers of a Call of Duty title. "Is there still code from Quake 3 in COD?". They dodge around it by saying something like "we cannot deny this but e use the most appropriate tech where needed".
While not confirmation, I wouldn't be surprised if there is a few nuggets of Q3 in that code base still doing some of the basics. That would be really cool if it is true.
It seems like unless you are someone like John Carmack or most of Nintendo, game dev tools are about what can get the best results quickest rather than any sort of technical specifics. It is a business after all.
"I tend to agree about the "async contamination" problem. The "async" system is optimized for someone who needs to run a very large web server, with a huge number of clients sending in requests. I've been pushing back against it creeping into areas that don't really need it."
100% this. As I say elsewhere in these threads: Rust is the language that Tokio ate. It isn't even just async viral-chain-effect, it's that on the whole crates for one async runtime are not even compatible with those of another, and so it's all really just about tokio.
Which sucks, if you're doing, y'know, systems programming or embedded (or games). Because tokio has no business in those domains.
It does in my domain of systems programming with async data handling. Tokio works like a dream - slipping into the background and just working so I can concentrate on the business logic.
> I'd expected some AAA title to be written in Rust by now. That hasn't happened, and it's probably not going to happen, for the reasons the author gives.
The main reason is that you can't ship that Rust code on PS5 in a sensible manner. People have tried, got useless toys to compile, but in the end even Embark gave up. I remember seeing something from them that they had moved Rust to server-only.
> I tend to agree about the "async contamination" problem.
Argh I have the same issue. Sure if you write JS or Python you probably need async. My current Java back end that has like 5 concurrent users does not need async everything making 10x the complexity.
> I'd expected some AAA titles to be written in Rust by now.
"AAA" titles are huge and/or high dev budgets. Even if a game is "starting from scratch" the engine development team are still likely taking code from previous projects to get started. Of course there are other factors. It could be a BIG RISK to move to another programming language when the team, despite frustrations, are already familiar with something else... like the perks C++ brings (you learn from trial-and-error)
Could you imagine learning Rust as-you-go... building a AAA title... and fighting the compiler? To me it is a huge risk!
That is my opinion.. but I am sure others will disagree. If there is anyone on (or did) a AAA title with Rust... I would be happy to hear more about it.
I am not saying it will never happen. Maybe a AAA title is currently in development in Rust. I honestly dont know. However, game developers... if they are looking into Rust... are also looking at Odin, Jai, or Zig. For gaming, I think they are better alternatives than Rust but (again) that is my opinion.
Now for smaller, indie games - the possibility of moving to Rust (or another language) is more likely. Likely a fair percentage have moved away from C++ now.
> * There are very few people doing serious 3D game work in Rust. There's Veloren, and my stuff, and maybe a few others. No big, popular titles. I'd expected some AAA title to be written in Rust by now. That hasn't happened, and it's probably not going to happen, for the reasons the author gives.
At one point the studio behind the Finals was writing game server code in Rust with an Unreal engine client. Not sure if that's true still
The studio you're talking about is Embark studios, and is openly pretty big on Rust [1]
I think it was rumored that their next project will use a Rust game engine, but I am not sure how it's going now.
> The "async" system is optimized for someone who needs to run a very large web server, with a huge number of clients sending in requests.
Can you please elaborate on this? I see a lot of similar concerns in other contexts too. Linux kernel's scheduler for example. Is it a throughput/latency tradeoff?
A perception among some that threads are expensive, especially when "wasted" on blocking I/O. And that using them in that domain "won't scale."
Putting aside that not all of use are building web applications (heterodox here in HN, I know)...
Most people in the real world with real applications will not hit the limits of what is possible and efficient and totally fine with thread-based architectures.
Plus the kernel has gotten more efficient with threads over the years.
Plus hardware has gotten way better, and better at handling concurrent access.
Plus async involves other trade-offs -- running a state machine behind the scenes that's doing the kinds of context switching the kernel & hardware already potentially does for threads, but in user space. If you ever pull up a debugger and step through an async Rust/tokio codebase, you'll get a good sense for what the overhead here we're talking about is.
That overhead is fine if you're sitting there blocking on your database server, or some HTTP socket, or some filesystem.
It's ... probably... not what you want if you're building a game or an operating system or an embedded device of some kind.
An additional problem with async in Rust right now is that it involves bringing in an async runtime, and giving it control over execution of async functions... but various things like thread spawning, channels, async locks, etc. are not standardized, and are specific per runtime. Which in the real world is always tokio.
So some piece of code you bring in in a crate, uses async, now you're having to fire up a tokio runtime. Even though you were potentially not building something that has anything to do with the kinds of things that tokio is targeted for ("scalable" network services.)
So even if you find an async runtime that's optimized in some other domain, etc (like glommio or smol or whatever) -- you're unlikely to even be able to use it with whatever famous upstream crate you want, which will have explicit dependencies into tokio.
There's a lot going on. Someone is doing a new third party viewer, Crystal Frost, in Unity. Linden Lab has a mobile viewer in alpha test. Rendering is PBR now for new objects. There are mirrors! Content upload is moving to glTF, to be compatible with everybody else.
Voice is switching from Vivox to WebRTC. Game controller support is in test. New users get better avatars. The dev staff is larger.
None of this is yet increasing Second Life usership much, but it remains the best metaverse around.
I thought the metaverse thing was going to be bigger. Meta spent so much money to produce so little.
As a game developer for about two decades, I've never considered Rust to be a good programming language choice.
My priorities are reasonable performances and the fastest iteration time possible.
Gameplay code should be flexible, we have tons and tons of edge cases _by design_ because this is the best way to create interesting games.
Compilation time is very important, but also a flexible enough programming structure, moving things around and changing your mind about the most desirable approach several times a day is common during heavy development phases.
We almost never have specifications, almost nothing is set until the game is done.
It is a different story for game engines, renderers, physics, audio, asset loaders etc. those are much closer to system programming but this is also not where we usually spend the most time, as a professional you're supposed to either use off-the-shelf engines or already made frameworks and libraries.
Also, ECS is, IMHO, a useful pattern for some systems, but it is a pain in the butt to use with gameplay or UI code.
> It is a different story for game engines, renderers, physics, audio, asset loaders etc. those are much closer to system programming but this is also not where we usually spend the most time, as a professional you're supposed to either use off-the-shelf engines or already made frameworks and libraries.
But this is where industry interest (the little there is) lies for Rust, is it not? This is what the AAA studios that are researching and prototyping are working on.
C++ is not a popular language to implement the actual game in for all the reasons you list. It is too slow to compile and too rigid. The people who actually build the games, make them tick, are all working in visual scripting languages.
I'm surprised no one has made such a language that is designed from the ground up to be used as such for rust. Nim/coffeescript come to mind, but they target non-rust languages. Lua would be close enough if it weren't so alien to everything people like about rust.
As a non-game dev who uses Rust and Elixir, Rust wouldn't be my first pick for a large gamedev studio for multiple reasons. As for alternatives worth evaluating: Crystal, Cython (compiled Python), or Nim could result in increased gamedev productivity over C++ or C#. Maybe even Go because the iteration and compile times are very fast, and the learning curve is very low.
Often in the past Lua has been used and in my experience it's been quite nice. It's very easy to bind, there's some nice editors out there and the performance is decent.
There's some other game-specific scripting languages that have popped up (angelscript and wren come to mind but there's more). I've not used them in full production products though. Mostly just kicked the tires.
Now that I think about it though, it's been almost 6 years since I've worked on an engine with lua support. Mainly because in the last few years I've been working with unity or unreal.
| Go because the iteration and compile times are very fast
Safety is important and for certain applications, Rust is unrivaled.
But for games, like web apps, where time to market and innovation can be just as if not more important than being free of runtime errors, Go is more suited to rapid development than Rust on compile times alone.
Of course, the libraries and support for both aren't quite there yet, so at this point neither is well suited to game dev.
> Cython (compiled Python), or Nim could result in increased gamedev productivity over C++ or C#
If you're starting from scratch, then maybe. Having had to crash learn games dev (ex VFX systems person) Unity + c# is just so nice to use. most of the easiness of python, but with proper strict typing. (which you can turn off, if you want)
plus the wealth of documentation, its great. I imagine unreal is quite good in that regard too.
I had similar thoughts, about Rust being a good match for game engines but not games. Maybe it suggests Rust game engines might want to include an interpreter for some higher level language to actually do the gamedev in.
Rust is pretty good for writing PL interpreters (and similar tooling) too, actually.
I know you're not asking for recommendations, but Lisp, particularly SBCL, really seems to check all your boxes. I say this as someone who generally reaches for Scheme when it comes to Lisps too.
There are a few game engines[0] for CL, but most of them seem to be catered specifically to 2D games.
> a flexible enough programming structure, moving things around and changing your mind about the most desirable approach several times a day is common during heavy development phases.
That's the kind of code for which Rust-like languages shine. Rich type systems make it easy to change your mind about things and make large changes to your code with confidence.
(Whether Rust tooling is actually at a level to take advantage of that is another question)
> That's the kind of code for which Rust-like languages shine. Rich type systems make it easy to change your mind about things and make large changes to your code with confidence.
I don't think this is true. Rust makes it easy to get the refactor right (generally speaking 100% right). But that's not what they're describing. They're describing where the ability to make the refactor fast, even if it doesn't work correctly (in the formal sense of correctly). That is to say, memory leaks and race conditions and all sorts of horrible nastiness may be tolerable during the dev process in exchange for trying out an idea more quickly.
This is, of course, significantly more work at the end to patch up all of the things you did, but if you don't have to do the full work on 99/100 iterations, or got to try out more iterations because of the quick turnaround time, that would be considered a win here.
Pretty much every compiled language with a static typesystem has that "large-scale refactoring support" though. That's not Rust's USP, on the contrary: a too strongly typed language can make refactoring actually harder than it needs be. The sweet spot is somewhere in the middle (where exactly is up for discussion of course).
>Rich type systems make it easy to change your mind about things and make large changes to your code with confidence.
To be fair, they need to be able to make large changes with confidence because what would be small changes in other languages tend to end up being very large changes in rust like languages.
> Also, ECS is, IMHO, a useful pattern for some systems, but it is a pain in the butt to use with gameplay or UI code.
Not a game developer, but each time I tried to make one not using ECS(or something at least similar in spirit) I quickly found myself not being able to proceed due to the sheer mess in the codebase.
That game (currently) has 88% positive reviews on steam and a 77 metacritic score with over 15.5k people playing the game right now (according to steamcharts.com)
I can't really comment on the quality of the game or experience or how buggy it feels because I've never played it, but I will say that counting fixed crash situations is a somewhat arbitrary and useless metric. If each of those crashes affected and was reported by a single person or even nobody because no regular person could really encounter it is a vastly different situation than if each of those crashes was experienced by even 1% of the users.
The criteria by which something is decided to mention in the patch notes is not always purely because the users care. Sometimes it's because the developers want to signal effort to user and/or upper management.
Maybe Mount and Blade was super boggy in the past and is still super buggy now so all the crashes fixed are just an indicator of how large the problem is for them and how bad the code still is. I dunno, you didn't really give any information to help on that front.
With Rust and the exact time iteration times, management and deadlines, you end up with the same amount, just theyre panic!() instead. Thats an improvement, sure, but its fighting a symptom.
I love Rust, but a crashing released game is better than a half-finished "perfect" game, or a game where you couldn't iterate quickly, and ended up with a perfectly tuned, unfun game.
Photoshop does crash. Trust me if you do enough image editing you'll know it's not even a super rare event. They're generally doing a poor job handling the situations where you have no enough storage or RAM.
Hard to know what TaleWorlds are actually optimising for because half the features of Bannerlord feel like they’ve never been played by a dev let alone iterated on.
My impression is that this is due to their non-robust programming style. They do not add fallback behavior when e.g. receiving a null object. It would still be a bug, but could be a log entry instead of crash.
I've been saying this for years. I've tried to get into Rust multiple times the past few years and one of the things I've tried was gamedev with Rust (specifically the library ggez when it was still being worked on, and a little bit of Bevy). I admittedly never got far, but I gave it a solid shot.
My experience was instantly terrible. Slow compile times and iterations, huge package downloads (my project folder was roughly 1gb for a simple 2D project), and of course Rust itself was difficult to get into with lifetimes and having to wrap and unwrap my variables constantly and getting into wrestling matches with the borrow checker.
I kept telling myself that everyone loves Rust and the community loves to rave about anything Rust-related and maybe I just don't get it, but it took some time to realize that no... It's just a terrible choice for it. I even tried to make UI with eGUI and was still miserable. Rust is a systems programming language but the community is trying to convince everyone should be used for general purpose stuff.
And my other biggest problem is that they keep painting other non-Rust things as being fundamentally flawed for not being Rust. "It's not memory safe" is the biggest one thrown around, but when was the last time memory safety was actually a big problem in games? Unity uses C# which is garbage collected, Godot uses its own scripting language which makes it nigh impossible to leak memory, Unreal AFAIK has its own tools that makes memory management trivial. Rust game development feels like a solution looking for a problem to fix.
I am curious about Bevy when it becomes mature and has its own editor, but for now I'm just not convinced gamedev with Rust will ever take off.
> And my other biggest problem is that they keep painting other non-Rust things as being fundamentally flawed for not being Rust. "It's not memory safe" is the biggest one thrown around, but when was the last time memory safety was actually a big problem in games? Unity uses C# which is garbage collected, Godot uses its own scripting language which makes it nigh impossible to leak memory, Unreal AFAIK has its own tools that makes memory management trivial. Rust game development feels like a solution looking for a problem to fix.
Memory safety may or may not be important in games, but the ability of engines like Bevy to analyze system dependencies and automatically scale to multiple CPUs is a big deal. Job queuing systems have been popular in gamedev for a very long time, and Rust's insistence on explicit declaration of mutability is a big part of the reason that "just works" in Bevy.
> but the ability of engines like Bevy to analyze system dependencies and automatically scale to multiple CPUs is a big deal
Is it? The article addresses that, and basically calls it a pointless feature that is almost never used and when it is the benefits are mostly lost because of real world needs and constraints, and that the problems it solves are easier solved through other solutions and add-on systems that are well understood.
I think this might be a case where explaining the real-world benefit instead of the theoretical benefit is needed, if only to counter what are very pointed criticisms that are definitely deeper than at the theoretical level.
It's a good feature, but still a niche one. It's a bit like choosing Unity only because of DOTS. For a few projects perhaps it make sense. But just a few ones.
I'm a Rust fan (mostly for embedded firmware with minimal deps), but even after 10 years of playing with the language it's not clear to me that advanced GUI or gamedev fits well with the borrow checker. It requires a significant paradigm shift in architecture, and I'm not convinced it's worth making that shift, especially if your application can tolerate a garbage collector (which many games and most UI apps can).
Agreed. Multiple languages exist. They can be part of {your, your team's} toolbox for different specific purposes. Some languages are set by other tools or by team members' backgrounds. Popularity also lends itself to greater availability of tools and Q&A forums. In the end, it's a better decision-making process to select what is most likely to be long-term productive for a specific project and team.
This might be controversial, but "Safety" and "Speed", in the same ecosystem, are not free. The cost is heavy syntax and heavy cognitive climbs. Why Rust was ever sold as a language for the masses is beyond me. A safe, fast, hard language is something you use for operating systems, aircraft, etc.
I adore Rust because it does all the things I remember being told to do in C, but without me remembering to do them: Error codes from all functions, Ownership models, etc. But those are not good reasons for me to use it for anything I wouldn't use C for.
> Rust game development feels like a solution looking for a problem to fix.
The same can be said for ordinary CRUD backends. Java, C#, Go and Typescript (Node, Deno or Bun) are all memory safe with good type systems and more than good enough performance. Evangelism around Rust is unfortunately still a thing. A good example is the latest hype in the community because some Google Manager said at a Rust conference that writing Rust is as fast as writing Go. Anyone having done more than a toy program in Rust and Go knows how wrong this statement is. The reasons are given in the article.
This is not necessarily a bad thing. Especially given that Rust is an immediate upgrade with no downsides when moving away from C or C++. It is easy to see with people never wanting to go back, which also involves getting companies and products to adopt it as you would otherwise be forced by the market to work with inferior tools.
As a counterexample, .NET suffers a lot from the lack of evangelism - big chunk of community that started out back in .net framework days still thinks of it as poorly as people outside the ecosystem because they never bothered to drop old and obsolete tools and targets and give new versions a proper try (as the code is often vastly simplified and performance is vastly better).
Other programming languages, not only Rust, also do better at self promotion - take for example Go that managed to convince everyone to put it in the same bucket as Rust (which, personally, I find absolutely insulting as C# is a much closer alternative to Rust both in performance, features and access to low-level bits).
The godot-rust project crates take a minor amount of adaptation to understand how it exposes the Godot object system in Rust but it's also pretty well developed.
Last time I tried Godot with C# in Visual studio, when I debugged I could not see the console output, and when I ran with the console output I could not debug (the breakpoints weren't hit). A Google search later and turns out it wasn't just me.
We're doing more and more of our back-end work with Rust. The main reason is the performance it provides. It's not just great for our end-users it's also so much cheaper in the modern world where we pay per mileage in the cloud. Part of what we really like about Rust, however, is actually exactly the variable ownership because it makes it very straight forward to enforce and control data-integrity and avoid race conditions. Even for programmers who would struggle to do so in C or C++.
I'm not sure whether or not that's even useful in game development. I've never done any form of game development beyond some Chess game I programmed in my first year of CS 30 years ago. But I'm actually really curious as to why you've struggled with variable ownership, because I'd frankly like to improve our on-boarding processes even more for new hires.
> my other biggest problem is that they keep painting other non-Rust things as being fundamentally flawed for not being Rust
Rust has a cult and it's best not to pay too much attention to it. Don't get me wrong, we're seeing great benefit in not just using Rust over C/C++ but also replacing more and more of our C# and Python services with it, but it's a very immature language and like any other programming language it's still just a tool. If it works for you, use it, if not... Well, use something that does.
Now I'm wondering how far people could go a hypothetical Rustscript* that transpiles to Rust (or hooks into rustc?), introduces extra features such as reflection, removes lifetimes, and changes the defaults around things like monomorphization.
If you're removing lifetimes from the script, I'm not sure how you're then transpiling to Rust, unless you wrap everything with reference counting, at which point you're better off using a language with GC.
Rust ain't Go but anything Go has can be used as an argument that Rust should try to do better in certain areas. ;)
Perhaps learn another language like Haskell, Swift, or Kotlin before Rust.
Get cargo-bloat, cargo-cache, and cargo-outdated.
Setup a memcache server and use sccache to accelerate Rust, C, and C++ compilations. It's not 100% but it's pretty awesome for things compiled at a stable build location.
Just like any platform, avoid dependencies wherever possible and use minimal crate features. Some Rust crates have an npm-like problem of dragging in zillions of dependencies.
> but when was the last time memory safety was actually a big problem in games? Unity uses C# which is garbage collected, Godot uses its own scripting language which makes it nigh impossible to leak memory, Unreal AFAIK has its own tools that makes memory management trivial.
So.... Sounds like memory safety is indeed a problem? Otherwise why do so many solutions exist for it?
Yeah, Rust definitely is not the only solution, or perhaps not even a good solution to this problem in the context of game development. But let's not pretend the problem itself doesn't exist?
> So.... Sounds like memory safety is indeed a problem? Otherwise why do so many solutions exist for it?
Memory safety and memory management are different things. Scripting languages remove the burden of manual memory management; as a side effect, they also tend to be memory safe, but that hasn't been the main motivation.
As I said in my own comment down thread, despite being a huge rust advocate, I sincerely agree with you here.
Rust is not a good language for actually writing games, and the fact that it is being sold as such is really detrimental to it in my opinion, because it is holding the ecosystem back. Rust is being pushed as a language for game logic, so people try out and realize it isn't very good at that, and so they just give up on Rust in the game development industry at all and leave, understandably! If Rust were more strategically positioned, it could get a lot farther. Where it should be focusing in the games industry is on game engines, where flexibility and quick iteration and easy prototyping and being able to just reach out and directly touch and control things isn't as important, but where concerns like the clarity and maintainability of the code base, stability of the software, resource ownership and management, and eeking out every ounce of performance all become important, and so the type system and static analysis guarantees of Rust are actually useful.
This is where, I'm disappointed to say, I think things like Bevy and Amethyst have severely hurt the Rust game development ecosystem. They aren't really game engines in the traditional sense, they are more like game frameworks like Love2D except written in Rust: they force you to statically link your game code to the engine code, and write your game logic in the same language your engine is written in. This means that game developers who just want to quickly prototype game mechanics and want to be able to iterate on them in order to refine them are forced to use a language that is far too focused on correctness, safety, static verifiability, and concerns like that to actually be usable as a programming language, and worse, it forces them to compile their game logic and the entire engine together and link them together in order to build their actual game and test it, massively increasing the weight of the process and basically ruling out hot reloading or making your game independent of any specific version of the engine, or its license. It puts them between a rock and a hard place, between using some other ecosystem, or using a language that simply unsuitable for a game development.
I think the far better solution (one which I plan to very slowly feel out with my embryo engine project, which is born out of my frustration of looking at the existing rust game engines and feeling like they are all kind of lying about what they are) would be to stop with the vaporware and the hype with Bevy and Amethyst and such, and actually build a proper game engine, like they are promising to be but are not, that is its own separate pre-compiled executable that game developers don't even need to mess with at all, that picks up game assets and game code written in a more flexible, dynamic, language that's better for prototyping, and runs them, something like what Unity or Godot or even Gamebryo do. Only then will the rust game development ecosystem take off, because it will no longer be forcing a language that just isn't good for that on to people.
I've done hobby gamedev in Bevy/Rust, Godot/C#, and Unity C#.
It's honestly somewhat baffling to me that folks will choose Rust for gamedev right now. The state of the open sourced tools are just not there yet, especially when compared to Godot, and at the same time these games are running on PC hardware which tends to get faster every year.
Also for ECS... one thing I tended to realize is that when developing a game, pigeonholing everything into an ECS can seriously tend to get in the way. A lot of (efficiently written) game code is best handled in an infrequent event-driven way.
An ECS backed game engine like Bevy can make big mobs more efficient, but few games will actually leverage this effectively for fun gameplay and at the same time modern PCs are fast as hell.
I think about Starcraft from 1998, created when virtually all PCs only had one core, and its 200 unit per faction cap. Blizzard hasn't increased this cap because it doesn't necessarily make the game more fun. Now should a gamedev today, 26 years later, making a 2d isometric game for the PC be worried about performant multithreading????
> I think about Starcraft from 1998, created when virtually all PCs only had one core, and its 200 unit per faction cap. Blizzard hasn't increased this cap because it doesn't necessarily make the game more fun.
Ah... Starcraft. It's 200 supply per player (hero units take 0 supply, zerglings are 0.5, and the supply cost goes up to 8 for battlecruisers for example). The limit is enforced when building a unit from a building. Map triggers can grant units and you can exceed the 200 supply limit.
The technical unit limit for the map was 1700, and was later in fact extended to 3400 by Blizzard. The EUD emulator (part of the official SC Remastered) allows for online custom games to be played without any third party tools on the player's part. Certain limits like sprites can be bypassed with this tool (for map makers) https://github.com/phu54321/euddraft/blob/master/plugins/unl...
EUD started out as a buffer overflow exploit which allowed custom maps to patch the game client's code. It was later fixed by blizzard but re-implemented as an emulator (with some restrictions).
These are definitely things that enhance gameplay for custom scenarios.
https://youtu.be/HEv_U9WV4PA?t=1541 (yes, that is a battlecruiser shooting nukes)
Complete distraction of a question -- for that video clip, what is the song playing at the time stamp you selected? Is that in-game music? I figure not.
Likewise - I've been learning Rust for four years now (significant C/C++/Python/Lua experience), and have written some reasonably complex apps in it, but I really just didn't get the Bevy / ECS "hype"...
I've tried to write several different types of games using it (with Bevy) in the past three years, and it just feels like shoe-horning something in.
But the biggest complaint I have with Bevy is that with all the refactoring that's been needed with the Bevy version upgrades: getting the code to compile again after the version upgrades has normally been fairly easy - but it then often didn't work correctly, and I'd have to spend time debugging the ECS system to work out what was wrong.
i.e. the "if it compiles, it'll almost certainly work" bonus of generic Rust code totally seems to fall down within Bevy.
I obviously understand that it's an in-development framework, in its early days, so some of that's on me for choosing it, but still, it's been a very painful experience, and I feel I've wasted a fairly significant amount of time over the past few years attempting it.
CPUs are way way faster, but RAM latency has barely improved in the past couple decades. That's why cache-optimized systems like ECS can still be a dramatic improvement when you're simulating a lot of stuff. Like, thousands of active objects.
They can be improvements, but you can do Data-Oriented Programming without ECS systems, i.e. Structure Of Arrays, which is what we often using in Rendering/Simulation for VFX for SIMD/GPU compute...
But similarly, ECSs can be slower, if they don't have some optimisations, i.e. spatial data structure lookups: just using a generic ECS "database" system without any first-class spatial knowledge / acceleration structure lookup ability, is likely going to be slower.
> I think about Starcraft from 1998, created when virtually all PCs only had one core, and its 200 unit per faction cap. Blizzard hasn't increased this cap because it doesn't necessarily make the game more fun.
That small scale was exactly why the game ends up being so much about micro, and while that may make it more competitive or interesting for spectators it makes it a lot less fun to play IMO. Total Annihilation and successors were a lot more fun, and a big part of that was not having arbitrary unit caps in a way that affected gameplay; expanding the limit from 500 to 1500 did genuinely make the game more fun.
supreme commanders very high unit cap leads to crazy end games. it allows your economy to grow exponentially for the entire game. which has a big impact on late game strategy
Many people are choosing Rust because they want to use Rust. Rust has the reputation being "the best" programming language: Fast, safe, reliable, modern. I can rely on that very much. Who wouldn't like the feeling of using the best tech for their project.
What many overlook is that using Rust has very high costs, but the edge over alternative languages is often only marginally - depending on the use case of course.
Those costs of Rust get in the way of developing the actual product. You loose speed, efficiency, but potentially gain no benefit to the users of your product.
Really sells the value of having a tight developer feedback loop: it shows hot reloading for code and graphics, a reversible debugger, live profiling with flame graphs, a data inspector with data breakpoints, time travel inspection with a scrub bar, session sharing and replay with the same scrub bar and direct links from the call stack to a breakpoint, and more.
Above the many niggles they had with Rust itself, this greatly helps me understand why Rust left them wanting more from their working environment. They say they've switched back to Unity with https://hotreload.net/ to try to capture some of that, and now I see why. (It's a shame that hot reloading tooling in Rust wasn't ready for them yet, but I see why they've moved on instead of waiting/contributing.)
My impression of Rust is that it's a very opinionated language that wants everybody to program in a specific way that emphasizes memory safety above everything. That's a good idea, I think, for the systems programming use cases that it was intended for. I don't see that as a particularly useful thing to value for game development. The part in the article about the Rust borrow checker constantly forcing refactors sounds extremely obnoxious to deal with.
I'd think that an ideal game dev language would be programmer time efficient, reasonably performant and designed for skilled programmers who can handle a language filled with footguns. Basically a better version of C such as a selective subset of C++ or a Golang without garbage collection. I just don't think the kinds of security bugs you get from C/C++ "unsafe" code are that big of a deal for games but they would be for a web site or an enterprise database.
> I just don't think the kinds of security bugs you get from C/C++ "unsafe" code are that big of a deal for games but they would be for a web site or an enterprise database.
Even for database engines specifically, modern C++ is essentially as safe as Rust and significantly more ergonomic. Rust's safety features can't reason about the case when all of your runtime objects live in explicitly paged memory with indefinite lifetimes and no fixed memory address, which is the norm in database kernels. You have to write the same code to make handling these objects safe and correct in Rust that you have to write in C++. You can't use normal pointers and allocators for this even if you wanted to.
Rust's safety is designed more for normal dynamic memory applications.
This isn't even close to being true. I think memory safety isn't as important for games as it is for most software (though it is still quite important for multiplayer games!). But even if you write the most modern C++ possible I guarantee you are going to spend some of your time debugging segfaults, memory corruption and heisenbugs. Don't try and claim "I don't write bugs". Everyone does.
This kind of extends to embedded/low level systems programming as well - the assumption that memory can only change as an effect of program execution just does not hold true there. What's the value of tracking mutability and data ownership when a DMA engine can just decide to overwrite the memory you supposedly have exclusive access to?
> I'd think that an ideal game dev language would be programmer time efficient, reasonably performant and designed for skilled programmers who can handle a language filled with footguns. Basically a better version of C such as a selective subset of C++ or a Golang without garbage collection.
I agree so much that I've been working on this for a whole year.
There is a sweet spot : non-GC, with pointers (but bounded), inference, basic OOP + tacking, and all the comforts of scripts. All in a good looking syntax without semi-colons.
For me, this is Odin-Lang, it doesn't meet all the requirements you have listed, but it's ergonomic, fast, and comes with extensive core and vendor libraries. It's all just fun and reasonable.
IMO it’s not opinionated enough. Golang for example doesn’t let you customize go fmt, while Rust does. Rust also has many ways to do things in general (mod.rs vs name_of_folder.rs for example) and seems to not want to provide a useful baseline for most projects via its standard library (unlike Golang).
But to go back to our subject: Rust is a great language and that’s all you need. I wish I could use it with unity.
Most modern languages are memory safe and they don't get called out for emphasizing that or being opinionated. I think with Rust that attention results from its choice of memory management model which gets in the way a lot in ways described in the article.
> My impression of Rust is that it's a very opinionated language
It's not though. There's only one thing Rust is opinionated about.
> that wants everybody to program in a specific way that emphasizes memory safety above everything.
Well yes, that is literally the core proposition and purpose of the language. That's like saying java is opinionated because it wants to manage the memory.
> I just don't think the kinds of security bugs you get from C/C++ "unsafe" code are that big of a deal for games
As soon as games are networked it starts being a problem, and these days non-networked games are pretty rare.
Rust also is opinionated that you don't want to write shared libraries or plugins. You can do both, but only if you drop down to memory unsafe C interfaces. The default is statically compile all applications into one program. Rust also really wants you do to use their build system and package manager, you can avoid both but everything will fight you.
Sort of, although Zig certainly pushes itself towards the embedded world. I have tried Zig a bit and like it a lot, and I am sure it would be better for game dev than Rust, but I don't want to pass allocators around all day to all the objects in my game.
> I'd think that an ideal game dev language would be programmer time efficient, reasonably performant and designed for skilled programmers who can handle a language filled with footguns
Sounds like Common Lisp or OCaml would work well. With Ocaml I find myself being able to iterate extremely quickly because of the inferred types and extremely fast compilation times. You also have the ability to tweak the GC to your needs and the assembly is easy to read.
> Rust as both language and community is so preoccupied with avoiding problems at all cost that it completely loses sight of what matters, delivering an experience that is so good that whatever problems are there aren't really important. This doesn't mean "ship crap games", it means focusing on the game being a good game, not on the code being good code.
I think this can be easily extrapolated to projects outside of game development as well.
User experience is ultimately all that matters. If you're in prototyping stages of whatever it is you're building, and games spend a lot of time in this phase, then your focus should always be on testing what the user experience will be like, rather than absolute code correctness, maintainability, and everything else that makes a long-term project successful.
The fact Rust seemingly can't deliver this rapid prototyping workflow should be a large factor when deciding which language to use.
I've been using Go as my main language for the better part of a decade now, and I think it strikes the perfect balance of code quality and rapid prototyping. It's far from the side of absolute freedom of a language like Python, which becomes a nightmare to work with after the prototyping phase is over (though this might have improved in the past few years), but it's also far from languages like Rust, and allows me to be very productive, very quickly, while also being easy to pick up for newcomers. I probably wouldn't pick it for GUI or game development either, though, but for things like CLI, network and web tooling, it's perfect.
To be fair, many (non-game dev) Rust projects I have seen/used do provide great user experience precisely because they are laser-focused on performance and have blown existing alternatives out of the water. (Think ripgrep, fzf, etc.)
Prototyping is certainly necessary but it shouldn't be at the cost of runtime performance – at least not too much –, because it will typically be very difficult to improve performance after the fact, which web development frameworks, and in particular shitty "web" applications like MS Teams are a testament to.
Starting by saying I fundamentally agree wrt iteration speed. This is ultimately why [C/C++]/Lua was such a thing for a while, and it seems quite plausible that you could benefit from a core engine in rust bound to a scripting language.
But ultimately I sense the subtext here is much the same as with other Rust problems: the object oriented baby has been thrown out with the bathwater, often in the name of premature optimisation, but also with a sense of misplaced religious purity regarding the evils of state and the merits of functional programming. There never was any OOP law that your inheritance hierarchy had to be insane, or that you had to create classes for absolutely every last thing. Now we have people hitting the opposite extreme where everything has to go through the same function switched on a pattern matched enum. One of the core problems with Rust is it lacks the mechanisms to allow moving adequately out of this tarpit.
I still think Rust might have a place at the lowest level core where it is all about shuffling arrays of things through compute units, but for the higher level pieces it is clearly the wrong thing to be using.
> but also with a sense of misplaced religious purity regarding the evils of state
To clarify, Rust isn't against state at all. Rust bends over backwards to make mutation possible, when it would have been far easier (and slower, and less usable) to have a fully-immutable language. What Rust is against is global mutable state, and an aversion to global mutable state isn't a religious position, it's a pragmatic position, because global mutable state makes concurrency (and reasoning about your code in general) completely intractable.
1000%, and this is something gamedevs (and, for quite some time, webdevs) are guilty of in the name of speed for quite some time. In both web and game dev, it's come back to bite when it's time to debug.
Concurrency is hard, and anything with a ton of user interaction or communication across multiple parties induces concurrency (never block the main thread and all).
I've been playing around with an idea about OOP for awhile, not sure if it'll ring true or not but I'll run it up the flagpole for feedback.
I think FP is a great way to program actions and agency but OOP is a great way to model the world. I like Rust's trait system because the polymorphism is based on what you want an object to do not what it is. But when you're creating models of the world it's usually really convenient and even accurate to use nested inheritance models. Maybe the original system for this is the flora/fauna taxonomy but it applies to a lot of things; like GUI elements or game models.
If this is correct, it might explain why the discourse is so polarized. Whether OOP is a blessing or a curse probably depends on whether you're using a programming language as a modelling language or as a logic/execution language.
It's not hard/fast but I would tend to agree with an approximation of this.
Back when I worked properly on big games the UI libs would often be trees of widgets with injectable functions for modifying the rendering, which is actually one of the points in this blog the writer would like. (The UI lib of classic Sims was exactly like that). These days the stuff I've done, although entirely in JS, at https://luduxia.com/ follows that pattern for the 3D components at least. The world is defined in an almost classic scene graph and then behaviour is added by attaching functions to pieces, which can be composed functionally.
Much of the anti-OOP noise is the result of people that have suffered from others creating hierarchies of the world too literally. Quite why it proves so difficult for developers to slow down and think about the right course of action is beyond me. They're also staggeringly resistant to changing afterwards.
Absolutely agree. I think people saw that a lot of games are written in C++ and got confused into thinking that the right thing to do is to build your entire game in a systems language. The fact that we have games written entirely in C++ is mostly just due to the enormous amount of inertia that game engines have, and the fact that many of them have origins that go back decades to a time when the programming language landscape and broader development ecosystem were completely different.
And now, the most popular generally available game engines right now are:
Unity - C++ in the engine, C# for game code
Godot - C++ in the engine code, GDScript or C# for game code
Unreal - C++ in the engine code, somewhat mangled C++ for game code BUT with also one of the most capable and widely used visual programming setups I have ever seen
I wouldn't be surprised if the "next great game engine" had a Rust core and some other language- I mean why not C# at this point?- for game code.
> I wouldn't be surprised if the "next great game engine" had a Rust core and some other language- I mean why not C# at this point?- for game code.
That's why, the first time I saw Bevy and Amathyst, I had an immediate "they're doing it wront$ reaction. IMHO, to be a true game engine in the modern sense, instead of merely a game framework, your engine needs to be a precompiled, standalone executable in a systems language that picks up, loads, and executes game scripts, data files, and assets that are totally separate from the engine itself and written in higher level languages. You don't want to be writing everything in a rigid systems language and especially don't want to have to compile your game logic and your engine together and then link them as if the engine were a library. That's why I'm (very slowly) feeling out what a proper game engine in Rust might be like with https://github.com/alexispurslane/embryo-engine. It will take me some time, since I have to learn real time computer graphics and a lot about game engines, but I've got the books, I've made a lot of progress in learning them, and the engine design and architecture is coming together very well in my big black notebook, so if you're interested, give the repo a watch ;)
I'm debating between embeddable common lisp (to satisfy my hacker impulses) or C# for the scripting language. I have figured out, I think, how I'll embed C# in Rust down to some pretty detailed steps, involving a two stage process, but .NET is so heavy I'm worried if it'll be worth it. I'd love input!
Obviously that is the intention, but the absence of libraries that manage to replicate what people manage fairly easily in other paradigms does show it's not sufficient.
golang is similar in this regard - it has interfaces and you can compose type structs, but the results become an unwieldy mess unless the developers are staggeringly disciplined, in which case they'll have a better time in something else anyway.
This makes a lot of sense. Wonder if Bevy will add support for GDScript or C# or something. I think it's generally opposed in the interest of ensuring the Rust devex is as good as possible, but it's coming eventually, I think.
A general bevy scripting crate has already been in the works, they were waiting on various things like be y reflect and other such features to be able to work properly and so forth. In other words it's already planned and there's a lot of work being done on it with a whole lot of dependent functionality coming out in every single release.
I've been writing a metaverse client in Rust for several years now. Works with Second Life and Open Simulator servers. Here's some video.[1] It's about 45,000 lines of safe Rust.
Notes:
* There are very few people doing serious 3D game work in Rust. There's Veloren, and my stuff, and maybe a few others. No big, popular titles. I'd expected some AAA title to be written in Rust by now. That hasn't happened, and it's probably not going to happen, for the reasons the author gives.
* He's right about the pain of refactoring and the difficulties of interconnecting different parts of the program. It's quite common for some change to require extensive plumbing work. If the client that talks to the servers needs to talk to the 2D GUI, it has to queue an event.
* The rendering situation is almost adequate, but the stack isn't finished and reliable yet. The 2D GUI systems are weak and require too much code per dialog box.
* I tend to agree about the "async contamination" problem. The "async" system is optimized for someone who needs to run a very large web server, with a huge number of clients sending in requests. I've been pushing back against it creeping into areas that don't really need it.
* I have less trouble with compile times than he does, because the metaverse client has no built-in "gameplay". A metaverse client is more like a 3D web browser than a game. All the objects and their behaviors come from the server. I can edit my part of the world from inside the live world. If the color or behavior or model of something needs to be changed, that's not something that requires a client recompile.
The people using C# and Unity on the same problem are making much faster progress.
[1] https://video.hardlimit.com/w/7usCE3v2RrWK6nuoSr4NHJ
I'm disinclined to believe that any AAA game will be written in Rust (one is free to insert "because Rust's gamedev ecosystem is immature" or "because AAA game development is increasingly conservative and risk-averse" at their discretion), yet I'm curious what led you to believe this. C++ became available in 1985, and didn't become popular for gamedev until the turn of the millenium, in the wake of Quake 3 (buoyed by the new features of C++98).
Borland C++ was pretty common and popular in 93 and we even had some not-so-great C++ compilers on Amiga in 92/93 that had some use in gamedev.
SimCity 2000 was written in C++, way back in '93 (although they started with Cfront)
An absolute fuckton of shareware games I was playing in the 90s were built with Turbo C++.
Maybe adoption of rust by gamedev community isn't the best thing to wish to happen to language. Maybe it is better to let other crowd to steer evolution of rust, letting system programming and gamedev drift apart
Go had google driving adoption, which in turn drove open source efforts. The language had to remain grounded to not interfere with the doing of building back-end services.
Rust had mozilla/servo which was ultimately unsuccessful. While there are more than a few companies uinf rust for small projects with tough performance guarantees - I haven't seen the “we manage 1-10 MM sloc of complex code using rust” type projects.
Wasn't this also because Microsoft had terrible support for C?
Since the mid-90's, a number of gamedevs moved to C++ but were unhappy with the results.. how OOP works, exception handling, the STL, etc.
My understanding is.. by late 90's.. many game developers, despite using C++, we still coding more inline with C programming than (proper) C++.
Mostly C code but using some features of C++ like, functions inside a struct, or using namespaces, that did not sacrifice compilation and runtime speed.
https://www.youtube.com/watch?v=9UOYps_3eM0
The SNES came on 1990 and even then it had it's own architecture and most games were written in pure assembly. The PlayStation had a MIPS CPU and was one of the first to popularize 3D graphics, the biggest complexity leap.
I believe your are seeing causation were only correlation should be given. C++ and more complex OOP languages just joined the scene when the games themselves became complex, because of hardware and market natural evolution
Then lot of comments here that games are best done in C++.
So why can't Rust be used for games?
What is really missing beyond an improved ecosystem of tools. All also built on Rust.
Why? Those kinds of game engines are enormous amounts of code, and there's little incentive to rewrite.
I do strongly disagree that we aren't ever going to see large-scale game development in Rust; it just takes time. Whether games adopt an engine is largely about that engine's maturity rather than anything about the language. Bevy is quite young; 0.13 doesn't even have support for animation blending yet (I landed that for 0.14).
While not confirmation, I wouldn't be surprised if there is a few nuggets of Q3 in that code base still doing some of the basics. That would be really cool if it is true.
It seems like unless you are someone like John Carmack or most of Nintendo, game dev tools are about what can get the best results quickest rather than any sort of technical specifics. It is a business after all.
100% this. As I say elsewhere in these threads: Rust is the language that Tokio ate. It isn't even just async viral-chain-effect, it's that on the whole crates for one async runtime are not even compatible with those of another, and so it's all really just about tokio.
Which sucks, if you're doing, y'know, systems programming or embedded (or games). Because tokio has no business in those domains.
Even there it's very problematic at scale unless you know what you're doing. async/await isn't zero cost, regardless of what people will tell you.
The main reason is that you can't ship that Rust code on PS5 in a sensible manner. People have tried, got useless toys to compile, but in the end even Embark gave up. I remember seeing something from them that they had moved Rust to server-only.
Really - why’s that?
Argh I have the same issue. Sure if you write JS or Python you probably need async. My current Java back end that has like 5 concurrent users does not need async everything making 10x the complexity.
"AAA" titles are huge and/or high dev budgets. Even if a game is "starting from scratch" the engine development team are still likely taking code from previous projects to get started. Of course there are other factors. It could be a BIG RISK to move to another programming language when the team, despite frustrations, are already familiar with something else... like the perks C++ brings (you learn from trial-and-error)
Could you imagine learning Rust as-you-go... building a AAA title... and fighting the compiler? To me it is a huge risk!
That is my opinion.. but I am sure others will disagree. If there is anyone on (or did) a AAA title with Rust... I would be happy to hear more about it.
I am not saying it will never happen. Maybe a AAA title is currently in development in Rust. I honestly dont know. However, game developers... if they are looking into Rust... are also looking at Odin, Jai, or Zig. For gaming, I think they are better alternatives than Rust but (again) that is my opinion.
Now for smaller, indie games - the possibility of moving to Rust (or another language) is more likely. Likely a fair percentage have moved away from C++ now.
At one point the studio behind the Finals was writing game server code in Rust with an Unreal engine client. Not sure if that's true still
[1] https://github.com/EmbarkStudios/rust-ecosystem
Can you please elaborate on this? I see a lot of similar concerns in other contexts too. Linux kernel's scheduler for example. Is it a throughput/latency tradeoff?
A perception among some that threads are expensive, especially when "wasted" on blocking I/O. And that using them in that domain "won't scale."
Putting aside that not all of use are building web applications (heterodox here in HN, I know)...
Most people in the real world with real applications will not hit the limits of what is possible and efficient and totally fine with thread-based architectures.
Plus the kernel has gotten more efficient with threads over the years.
Plus hardware has gotten way better, and better at handling concurrent access.
Plus async involves other trade-offs -- running a state machine behind the scenes that's doing the kinds of context switching the kernel & hardware already potentially does for threads, but in user space. If you ever pull up a debugger and step through an async Rust/tokio codebase, you'll get a good sense for what the overhead here we're talking about is.
That overhead is fine if you're sitting there blocking on your database server, or some HTTP socket, or some filesystem.
It's ... probably... not what you want if you're building a game or an operating system or an embedded device of some kind.
An additional problem with async in Rust right now is that it involves bringing in an async runtime, and giving it control over execution of async functions... but various things like thread spawning, channels, async locks, etc. are not standardized, and are specific per runtime. Which in the real world is always tokio.
So some piece of code you bring in in a crate, uses async, now you're having to fire up a tokio runtime. Even though you were potentially not building something that has anything to do with the kinds of things that tokio is targeted for ("scalable" network services.)
So even if you find an async runtime that's optimized in some other domain, etc (like glommio or smol or whatever) -- you're unlikely to even be able to use it with whatever famous upstream crate you want, which will have explicit dependencies into tokio.
None of this is yet increasing Second Life usership much, but it remains the best metaverse around.
I thought the metaverse thing was going to be bigger. Meta spent so much money to produce so little.
My priorities are reasonable performances and the fastest iteration time possible.
Gameplay code should be flexible, we have tons and tons of edge cases _by design_ because this is the best way to create interesting games.
Compilation time is very important, but also a flexible enough programming structure, moving things around and changing your mind about the most desirable approach several times a day is common during heavy development phases.
We almost never have specifications, almost nothing is set until the game is done.
It is a different story for game engines, renderers, physics, audio, asset loaders etc. those are much closer to system programming but this is also not where we usually spend the most time, as a professional you're supposed to either use off-the-shelf engines or already made frameworks and libraries.
Also, ECS is, IMHO, a useful pattern for some systems, but it is a pain in the butt to use with gameplay or UI code.
But this is where industry interest (the little there is) lies for Rust, is it not? This is what the AAA studios that are researching and prototyping are working on.
C++ is not a popular language to implement the actual game in for all the reasons you list. It is too slow to compile and too rigid. The people who actually build the games, make them tick, are all working in visual scripting languages.
Gameplay code is still better written with code, C# or C++ or sometimes Lua.
I'm surprised no one has made such a language that is designed from the ground up to be used as such for rust. Nim/coffeescript come to mind, but they target non-rust languages. Lua would be close enough if it weren't so alien to everything people like about rust.
There's some other game-specific scripting languages that have popped up (angelscript and wren come to mind but there's more). I've not used them in full production products though. Mostly just kicked the tires.
Now that I think about it though, it's been almost 6 years since I've worked on an engine with lua support. Mainly because in the last few years I've been working with unity or unreal.
Safety is important and for certain applications, Rust is unrivaled.
But for games, like web apps, where time to market and innovation can be just as if not more important than being free of runtime errors, Go is more suited to rapid development than Rust on compile times alone.
Of course, the libraries and support for both aren't quite there yet, so at this point neither is well suited to game dev.
If you're starting from scratch, then maybe. Having had to crash learn games dev (ex VFX systems person) Unity + c# is just so nice to use. most of the easiness of python, but with proper strict typing. (which you can turn off, if you want)
plus the wealth of documentation, its great. I imagine unreal is quite good in that regard too.
I read on a recent HN thread that Crystal compilation is slow due to its type inference, IIRC.
Though 1.18 helped a lot, you'd have to do some major persuasion to game devs that Go's gc is the kind of thing they'd want in their game.
---
EDIT: Not sure the downvote, Go is know for its (historically at least) unsuitability for RTC or game dev.
Rust is pretty good for writing PL interpreters (and similar tooling) too, actually.
There are a few game engines[0] for CL, but most of them seem to be catered specifically to 2D games.
[0] https://github.com/CodyReichert/awesome-cl?tab=readme-ov-fil...
That's the kind of code for which Rust-like languages shine. Rich type systems make it easy to change your mind about things and make large changes to your code with confidence.
(Whether Rust tooling is actually at a level to take advantage of that is another question)
I don't think this is true. Rust makes it easy to get the refactor right (generally speaking 100% right). But that's not what they're describing. They're describing where the ability to make the refactor fast, even if it doesn't work correctly (in the formal sense of correctly). That is to say, memory leaks and race conditions and all sorts of horrible nastiness may be tolerable during the dev process in exchange for trying out an idea more quickly.
This is, of course, significantly more work at the end to patch up all of the things you did, but if you don't have to do the full work on 99/100 iterations, or got to try out more iterations because of the quick turnaround time, that would be considered a win here.
To be fair, they need to be able to make large changes with confidence because what would be small changes in other languages tend to end up being very large changes in rust like languages.
Not a game developer, but each time I tried to make one not using ECS(or something at least similar in spirit) I quickly found myself not being able to proceed due to the sheer mess in the codebase.
How does one normally avoid that?
I'd love to see a language built around ECS. I wonder how nice it can be in a language syntax where ECS is the easiest thing you can do.
I bought Mount & Blade II Bannerlord in 2020-03-30. I love it to death, but come on...
Maybe feeling like you're iterating fast isn't the same as getting to the destination faster.Edit: Lol guys calm down with the down-vote party. I was counting crashes, not bugs:
Does your C++ not crash, just theirs?Thats a lot of happy customers.
The criteria by which something is decided to mention in the patch notes is not always purely because the users care. Sometimes it's because the developers want to signal effort to user and/or upper management.
Maybe Mount and Blade was super boggy in the past and is still super buggy now so all the crashes fixed are just an indicator of how large the problem is for them and how bad the code still is. I dunno, you didn't really give any information to help on that front.
It didn't stop Adobe from being worth 200B.
A lot of those crashes might simply be called a "panic" in Rust.
https://github.com/int19h/Bannerlord.CSharp.Scripting
which in turn makes it a lot easier and more convenient to mod. Try that with Rust...
I've been saying this for years. I've tried to get into Rust multiple times the past few years and one of the things I've tried was gamedev with Rust (specifically the library ggez when it was still being worked on, and a little bit of Bevy). I admittedly never got far, but I gave it a solid shot.
My experience was instantly terrible. Slow compile times and iterations, huge package downloads (my project folder was roughly 1gb for a simple 2D project), and of course Rust itself was difficult to get into with lifetimes and having to wrap and unwrap my variables constantly and getting into wrestling matches with the borrow checker.
I kept telling myself that everyone loves Rust and the community loves to rave about anything Rust-related and maybe I just don't get it, but it took some time to realize that no... It's just a terrible choice for it. I even tried to make UI with eGUI and was still miserable. Rust is a systems programming language but the community is trying to convince everyone should be used for general purpose stuff.
And my other biggest problem is that they keep painting other non-Rust things as being fundamentally flawed for not being Rust. "It's not memory safe" is the biggest one thrown around, but when was the last time memory safety was actually a big problem in games? Unity uses C# which is garbage collected, Godot uses its own scripting language which makes it nigh impossible to leak memory, Unreal AFAIK has its own tools that makes memory management trivial. Rust game development feels like a solution looking for a problem to fix.
I am curious about Bevy when it becomes mature and has its own editor, but for now I'm just not convinced gamedev with Rust will ever take off.
Memory safety may or may not be important in games, but the ability of engines like Bevy to analyze system dependencies and automatically scale to multiple CPUs is a big deal. Job queuing systems have been popular in gamedev for a very long time, and Rust's insistence on explicit declaration of mutability is a big part of the reason that "just works" in Bevy.
Is it? The article addresses that, and basically calls it a pointless feature that is almost never used and when it is the benefits are mostly lost because of real world needs and constraints, and that the problems it solves are easier solved through other solutions and add-on systems that are well understood.
I think this might be a case where explaining the real-world benefit instead of the theoretical benefit is needed, if only to counter what are very pointed criticisms that are definitely deeper than at the theoretical level.
We've been promised automatic CPU scaling in programming languages since at least 2001, and I've yet to see any practical version of it.
Seems promising, very React-esque with little boilerplate
I adore Rust because it does all the things I remember being told to do in C, but without me remembering to do them: Error codes from all functions, Ownership models, etc. But those are not good reasons for me to use it for anything I wouldn't use C for.
The same can be said for ordinary CRUD backends. Java, C#, Go and Typescript (Node, Deno or Bun) are all memory safe with good type systems and more than good enough performance. Evangelism around Rust is unfortunately still a thing. A good example is the latest hype in the community because some Google Manager said at a Rust conference that writing Rust is as fast as writing Go. Anyone having done more than a toy program in Rust and Go knows how wrong this statement is. The reasons are given in the article.
As a counterexample, .NET suffers a lot from the lack of evangelism - big chunk of community that started out back in .net framework days still thinks of it as poorly as people outside the ecosystem because they never bothered to drop old and obsolete tools and targets and give new versions a proper try (as the code is often vastly simplified and performance is vastly better).
Other programming languages, not only Rust, also do better at self promotion - take for example Go that managed to convince everyone to put it in the same bucket as Rust (which, personally, I find absolutely insulting as C# is a much closer alternative to Rust both in performance, features and access to low-level bits).
I'm not sure whether or not that's even useful in game development. I've never done any form of game development beyond some Chess game I programmed in my first year of CS 30 years ago. But I'm actually really curious as to why you've struggled with variable ownership, because I'd frankly like to improve our on-boarding processes even more for new hires.
> my other biggest problem is that they keep painting other non-Rust things as being fundamentally flawed for not being Rust
Rust has a cult and it's best not to pay too much attention to it. Don't get me wrong, we're seeing great benefit in not just using Rust over C/C++ but also replacing more and more of our C# and Python services with it, but it's a very immature language and like any other programming language it's still just a tool. If it works for you, use it, if not... Well, use something that does.
is not something that exists in the real world.
* name intentionally made to make people angry
Perhaps learn another language like Haskell, Swift, or Kotlin before Rust.
Get cargo-bloat, cargo-cache, and cargo-outdated.
Setup a memcache server and use sccache to accelerate Rust, C, and C++ compilations. It's not 100% but it's pretty awesome for things compiled at a stable build location.
Just like any platform, avoid dependencies wherever possible and use minimal crate features. Some Rust crates have an npm-like problem of dragging in zillions of dependencies.
So.... Sounds like memory safety is indeed a problem? Otherwise why do so many solutions exist for it?
Yeah, Rust definitely is not the only solution, or perhaps not even a good solution to this problem in the context of game development. But let's not pretend the problem itself doesn't exist?
Memory safety and memory management are different things. Scripting languages remove the burden of manual memory management; as a side effect, they also tend to be memory safe, but that hasn't been the main motivation.
Rust is not a good language for actually writing games, and the fact that it is being sold as such is really detrimental to it in my opinion, because it is holding the ecosystem back. Rust is being pushed as a language for game logic, so people try out and realize it isn't very good at that, and so they just give up on Rust in the game development industry at all and leave, understandably! If Rust were more strategically positioned, it could get a lot farther. Where it should be focusing in the games industry is on game engines, where flexibility and quick iteration and easy prototyping and being able to just reach out and directly touch and control things isn't as important, but where concerns like the clarity and maintainability of the code base, stability of the software, resource ownership and management, and eeking out every ounce of performance all become important, and so the type system and static analysis guarantees of Rust are actually useful.
This is where, I'm disappointed to say, I think things like Bevy and Amethyst have severely hurt the Rust game development ecosystem. They aren't really game engines in the traditional sense, they are more like game frameworks like Love2D except written in Rust: they force you to statically link your game code to the engine code, and write your game logic in the same language your engine is written in. This means that game developers who just want to quickly prototype game mechanics and want to be able to iterate on them in order to refine them are forced to use a language that is far too focused on correctness, safety, static verifiability, and concerns like that to actually be usable as a programming language, and worse, it forces them to compile their game logic and the entire engine together and link them together in order to build their actual game and test it, massively increasing the weight of the process and basically ruling out hot reloading or making your game independent of any specific version of the engine, or its license. It puts them between a rock and a hard place, between using some other ecosystem, or using a language that simply unsuitable for a game development.
I think the far better solution (one which I plan to very slowly feel out with my embryo engine project, which is born out of my frustration of looking at the existing rust game engines and feeling like they are all kind of lying about what they are) would be to stop with the vaporware and the hype with Bevy and Amethyst and such, and actually build a proper game engine, like they are promising to be but are not, that is its own separate pre-compiled executable that game developers don't even need to mess with at all, that picks up game assets and game code written in a more flexible, dynamic, language that's better for prototyping, and runs them, something like what Unity or Godot or even Gamebryo do. Only then will the rust game development ecosystem take off, because it will no longer be forcing a language that just isn't good for that on to people.
It's honestly somewhat baffling to me that folks will choose Rust for gamedev right now. The state of the open sourced tools are just not there yet, especially when compared to Godot, and at the same time these games are running on PC hardware which tends to get faster every year.
Also for ECS... one thing I tended to realize is that when developing a game, pigeonholing everything into an ECS can seriously tend to get in the way. A lot of (efficiently written) game code is best handled in an infrequent event-driven way.
An ECS backed game engine like Bevy can make big mobs more efficient, but few games will actually leverage this effectively for fun gameplay and at the same time modern PCs are fast as hell.
I think about Starcraft from 1998, created when virtually all PCs only had one core, and its 200 unit per faction cap. Blizzard hasn't increased this cap because it doesn't necessarily make the game more fun. Now should a gamedev today, 26 years later, making a 2d isometric game for the PC be worried about performant multithreading????
Ah... Starcraft. It's 200 supply per player (hero units take 0 supply, zerglings are 0.5, and the supply cost goes up to 8 for battlecruisers for example). The limit is enforced when building a unit from a building. Map triggers can grant units and you can exceed the 200 supply limit.
The technical unit limit for the map was 1700, and was later in fact extended to 3400 by Blizzard. The EUD emulator (part of the official SC Remastered) allows for online custom games to be played without any third party tools on the player's part. Certain limits like sprites can be bypassed with this tool (for map makers) https://github.com/phu54321/euddraft/blob/master/plugins/unl...
EUD started out as a buffer overflow exploit which allowed custom maps to patch the game client's code. It was later fixed by blizzard but re-implemented as an emulator (with some restrictions).
These are definitely things that enhance gameplay for custom scenarios. https://youtu.be/HEv_U9WV4PA?t=1541 (yes, that is a battlecruiser shooting nukes)
I've tried to write several different types of games using it (with Bevy) in the past three years, and it just feels like shoe-horning something in.
But the biggest complaint I have with Bevy is that with all the refactoring that's been needed with the Bevy version upgrades: getting the code to compile again after the version upgrades has normally been fairly easy - but it then often didn't work correctly, and I'd have to spend time debugging the ECS system to work out what was wrong.
i.e. the "if it compiles, it'll almost certainly work" bonus of generic Rust code totally seems to fall down within Bevy.
I obviously understand that it's an in-development framework, in its early days, so some of that's on me for choosing it, but still, it's been a very painful experience, and I feel I've wasted a fairly significant amount of time over the past few years attempting it.
But similarly, ECSs can be slower, if they don't have some optimisations, i.e. spatial data structure lookups: just using a generic ECS "database" system without any first-class spatial knowledge / acceleration structure lookup ability, is likely going to be slower.
That small scale was exactly why the game ends up being so much about micro, and while that may make it more competitive or interesting for spectators it makes it a lot less fun to play IMO. Total Annihilation and successors were a lot more fun, and a big part of that was not having arbitrary unit caps in a way that affected gameplay; expanding the limit from 500 to 1500 did genuinely make the game more fun.
Starcraft late-game is hoarding resources and running out your opponent's patience while looking for a slip up.
What many overlook is that using Rust has very high costs, but the edge over alternative languages is often only marginally - depending on the use case of course.
Those costs of Rust get in the way of developing the actual product. You loose speed, efficiency, but potentially gain no benefit to the users of your product.
In my opinion this is a result of big mobs having poor performance. When players get to choose they seem to like having more mobs thrown at them.
This can also be limiting for interactable objects.
https://www.youtube.com/watch?v=72y2EC5fkcE
Really sells the value of having a tight developer feedback loop: it shows hot reloading for code and graphics, a reversible debugger, live profiling with flame graphs, a data inspector with data breakpoints, time travel inspection with a scrub bar, session sharing and replay with the same scrub bar and direct links from the call stack to a breakpoint, and more.
Above the many niggles they had with Rust itself, this greatly helps me understand why Rust left them wanting more from their working environment. They say they've switched back to Unity with https://hotreload.net/ to try to capture some of that, and now I see why. (It's a shame that hot reloading tooling in Rust wasn't ready for them yet, but I see why they've moved on instead of waiting/contributing.)
Does anyone knowledgeable here have a sense for whether there are any insurmountable roadblocks to bringing hot reload to Godot?
I'd think that an ideal game dev language would be programmer time efficient, reasonably performant and designed for skilled programmers who can handle a language filled with footguns. Basically a better version of C such as a selective subset of C++ or a Golang without garbage collection. I just don't think the kinds of security bugs you get from C/C++ "unsafe" code are that big of a deal for games but they would be for a web site or an enterprise database.
Even for database engines specifically, modern C++ is essentially as safe as Rust and significantly more ergonomic. Rust's safety features can't reason about the case when all of your runtime objects live in explicitly paged memory with indefinite lifetimes and no fixed memory address, which is the norm in database kernels. You have to write the same code to make handling these objects safe and correct in Rust that you have to write in C++. You can't use normal pointers and allocators for this even if you wanted to.
Rust's safety is designed more for normal dynamic memory applications.
This isn't even close to being true. I think memory safety isn't as important for games as it is for most software (though it is still quite important for multiplayer games!). But even if you write the most modern C++ possible I guarantee you are going to spend some of your time debugging segfaults, memory corruption and heisenbugs. Don't try and claim "I don't write bugs". Everyone does.
There is a sweet spot : non-GC, with pointers (but bounded), inference, basic OOP + tacking, and all the comforts of scripts. All in a good looking syntax without semi-colons.
So you can program fast and get a fast program.
https://odin-lang.org/
And it takes a lot of people to make good tooling.
But to go back to our subject: Rust is a great language and that’s all you need. I wish I could use it with unity.
It's not though. There's only one thing Rust is opinionated about.
> that wants everybody to program in a specific way that emphasizes memory safety above everything.
Well yes, that is literally the core proposition and purpose of the language. That's like saying java is opinionated because it wants to manage the memory.
> I just don't think the kinds of security bugs you get from C/C++ "unsafe" code are that big of a deal for games
As soon as games are networked it starts being a problem, and these days non-networked games are pretty rare.
So have your network protocol parser in Rust and the entire rest of your game in whatever the hell you want.
All the practical safety you could desire without any language constraints for the other 99% of the code
Go without GC is more like a Go and Zig baby.
Sounds like Common Lisp or OCaml would work well. With Ocaml I find myself being able to iterate extremely quickly because of the inferred types and extremely fast compilation times. You also have the ability to tweak the GC to your needs and the assembly is easy to read.
Lisp is well… built for interactive development
Deleted Comment
This sums it up for me:
> Rust as both language and community is so preoccupied with avoiding problems at all cost that it completely loses sight of what matters, delivering an experience that is so good that whatever problems are there aren't really important. This doesn't mean "ship crap games", it means focusing on the game being a good game, not on the code being good code.
I think this can be easily extrapolated to projects outside of game development as well.
User experience is ultimately all that matters. If you're in prototyping stages of whatever it is you're building, and games spend a lot of time in this phase, then your focus should always be on testing what the user experience will be like, rather than absolute code correctness, maintainability, and everything else that makes a long-term project successful.
The fact Rust seemingly can't deliver this rapid prototyping workflow should be a large factor when deciding which language to use.
I've been using Go as my main language for the better part of a decade now, and I think it strikes the perfect balance of code quality and rapid prototyping. It's far from the side of absolute freedom of a language like Python, which becomes a nightmare to work with after the prototyping phase is over (though this might have improved in the past few years), but it's also far from languages like Rust, and allows me to be very productive, very quickly, while also being easy to pick up for newcomers. I probably wouldn't pick it for GUI or game development either, though, but for things like CLI, network and web tooling, it's perfect.
Prototyping is certainly necessary but it shouldn't be at the cost of runtime performance – at least not too much –, because it will typically be very difficult to improve performance after the fact, which web development frameworks, and in particular shitty "web" applications like MS Teams are a testament to.
As always, it's about balance.
I think these are great examples of where prototyping and rapid iteration are really not needed at all, and hence Rust shines here.
Writing a game is completely different.
It should be but current state of web will show you that it is often not.
But ultimately I sense the subtext here is much the same as with other Rust problems: the object oriented baby has been thrown out with the bathwater, often in the name of premature optimisation, but also with a sense of misplaced religious purity regarding the evils of state and the merits of functional programming. There never was any OOP law that your inheritance hierarchy had to be insane, or that you had to create classes for absolutely every last thing. Now we have people hitting the opposite extreme where everything has to go through the same function switched on a pattern matched enum. One of the core problems with Rust is it lacks the mechanisms to allow moving adequately out of this tarpit.
I still think Rust might have a place at the lowest level core where it is all about shuffling arrays of things through compute units, but for the higher level pieces it is clearly the wrong thing to be using.
To clarify, Rust isn't against state at all. Rust bends over backwards to make mutation possible, when it would have been far easier (and slower, and less usable) to have a fully-immutable language. What Rust is against is global mutable state, and an aversion to global mutable state isn't a religious position, it's a pragmatic position, because global mutable state makes concurrency (and reasoning about your code in general) completely intractable.
Concurrency is hard, and anything with a ton of user interaction or communication across multiple parties induces concurrency (never block the main thread and all).
Deleted Comment
I think FP is a great way to program actions and agency but OOP is a great way to model the world. I like Rust's trait system because the polymorphism is based on what you want an object to do not what it is. But when you're creating models of the world it's usually really convenient and even accurate to use nested inheritance models. Maybe the original system for this is the flora/fauna taxonomy but it applies to a lot of things; like GUI elements or game models.
If this is correct, it might explain why the discourse is so polarized. Whether OOP is a blessing or a curse probably depends on whether you're using a programming language as a modelling language or as a logic/execution language.
Back when I worked properly on big games the UI libs would often be trees of widgets with injectable functions for modifying the rendering, which is actually one of the points in this blog the writer would like. (The UI lib of classic Sims was exactly like that). These days the stuff I've done, although entirely in JS, at https://luduxia.com/ follows that pattern for the 3D components at least. The world is defined in an almost classic scene graph and then behaviour is added by attaching functions to pieces, which can be composed functionally.
Much of the anti-OOP noise is the result of people that have suffered from others creating hierarchies of the world too literally. Quite why it proves so difficult for developers to slow down and think about the right course of action is beyond me. They're also staggeringly resistant to changing afterwards.
There's a reason Simula was the first OOP language.
https://en.m.wikipedia.org/wiki/Simula
And now, the most popular generally available game engines right now are: Unity - C++ in the engine, C# for game code Godot - C++ in the engine code, GDScript or C# for game code Unreal - C++ in the engine code, somewhat mangled C++ for game code BUT with also one of the most capable and widely used visual programming setups I have ever seen
I wouldn't be surprised if the "next great game engine" had a Rust core and some other language- I mean why not C# at this point?- for game code.
That's why, the first time I saw Bevy and Amathyst, I had an immediate "they're doing it wront$ reaction. IMHO, to be a true game engine in the modern sense, instead of merely a game framework, your engine needs to be a precompiled, standalone executable in a systems language that picks up, loads, and executes game scripts, data files, and assets that are totally separate from the engine itself and written in higher level languages. You don't want to be writing everything in a rigid systems language and especially don't want to have to compile your game logic and your engine together and then link them as if the engine were a library. That's why I'm (very slowly) feeling out what a proper game engine in Rust might be like with https://github.com/alexispurslane/embryo-engine. It will take me some time, since I have to learn real time computer graphics and a lot about game engines, but I've got the books, I've made a lot of progress in learning them, and the engine design and architecture is coming together very well in my big black notebook, so if you're interested, give the repo a watch ;)
I'm debating between embeddable common lisp (to satisfy my hacker impulses) or C# for the scripting language. I have figured out, I think, how I'll embed C# in Rust down to some pretty detailed steps, involving a two stage process, but .NET is so heavy I'm worried if it'll be worth it. I'd love input!
golang is similar in this regard - it has interfaces and you can compose type structs, but the results become an unwieldy mess unless the developers are staggeringly disciplined, in which case they'll have a better time in something else anyway.