This was a really good summary of what Rust feels like in my opinion. I’m still a beginner myself but I recognize what this article is saying very much.

The hacker news comments are as usual very good too:

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

  • sugar_in_your_tea@sh.itjust.works
    link
    fedilink
    arrow-up
    1
    ·
    edit-2
    8 months ago

    First of all, I think Rust is a poor choice for games for a few reasons:

    • you’re better off using a bigger game engine - Rust game engines are hobby projects, whereas Godot and Unreal Engine are production projects
    • games often have complex data structures that don’t play nice with the borrow checker - you can make it work, but to get great performance, you’ll need to irritate a lot on non-game logic; save those tricks for servers, kernels, etc
    • performance critical paths tend to be in the engine, not game logic

    In general, my advice is:

    • use scripting languages with a popular engine by default, optimize in something compiled (so Rust as a library language)
    • don’t optimize performance until the logic is stable
    • handle threading from the start

    And specific reactions to the article:

    Throw away code in Rust

    In other languages one can write code with “I can throw this away later” in mind

    The Rust equivalent is to wrap everything in a Box and use unwrap() everywhere. For multithreaded logic, wrap it in Arc as well. That tends to eliminate most borrow checker problems.

    So I do that when working on a new part of the app, and then fix things later. I just did a round of that this past weekend on a project where I switched everything to &str, removed unwrap(), etc.

    So you can absolutely do the “tech debt now, fix later” approach in Rust.

    ECS and games specific stuff

    ECS… in games performance matters

    Agreed, but it’s matters far more in the engine than in game logic. Just do the inefficient thing now and save the refactor for later.

    The OP says they want to use something else to kick the performance can down the road, but for some reason isn’t willing to do the same in Rust. Not sure why that is…

    I haven’t used an ECS much, so I’ll stop here.

    I’m not evaluating Rust from the perspective of technical curiosities or “this scratches the right brain itch”. I want to make real games that will get shipped to real people (not developers) in reasonable amount of time

    So why go with experimental libraries in Rust like Bevy? AFAIK, the number of people shipping real games in Bevy is probably in the single digits.

    Use a big engine like Godot or Unreal if you want to ship a real game. Use something like Bevy if you want to scratch the brain itch.

    Making a fun & interesting games is about rapid prototyping and iteration, Rust’s values are everything but that

    Right, which is why most studios write game logic in a scripting language first and move heavy logic to something faster.

    I started a game project with a friend. They wanted C++ and I wanted Rust, so we wrote in Lua and wrote competing servers. The vast majority of the logic was (and still is) in Lua, with only a small amount in C++ (we abandoned my Rust code because the other dev didn’t understand it).

    Use the right tool for the job…

    Rust community

    Because of the general vibes in the Rust community it’s very common for people to receive very positive reinforcement on what they’re building

    Sure, and this is a good thing. But don’t mistake positive reinforcement for that being the right way to do something in your case.

    I evangelize Rust quite a bit, but I also use Python and Lua for things that need fast iteration.

    Rust gamedev ecosystem lives on hype

    Agreed, which is why I bailed after a week or so messing with stuff. It was obvious at the time that everything was half-baked and I’d be fighting the engine more than my game logic.

    Rust game dev projects are a cool hobby, I wouldn’t rely on any for a production game though.

    GUI situation in Rust is terrible

    Agreed.

    Macros and reflection

    Procedural macros are not even “we have reflection at home”

    They never were. I don’t know who claimed they were, because that’s a fundamental misunderstanding of what reflection is.

    There are two types of reflection:

    • runtime reflection - basically what Go, Java, and C# have; I’ve mostly used Go’s, which is pretty nice, but there are plenty of footguns there
    • compile time reflection - the only one I’m familiar with is D’s compile time reflection library

    Rust macros are like halfway to compile-time reflection, but it’s still a long way off. It’s great for automating trait impls and other forms of code generation, but it’s not enough to actually do reflection.

    Also, compile time reflection, while powerful, is not nearly as nice to use as runtime reflection, and Rust will likely never have that. So design your problems so reflection isn’t needed, and don’t lie and tell others Rust has it.

    Hot reloading and dev loop

    Hot reloading is more important

    Agreed. Use a scripting language for rapid iteration.

    But it’s especially sad for a language that aims to be so fast and optimal to have to resolve to wasting cycles on re-allocating memory more often than one would like, just to stay productive.

    I think this is the main problem here. OP seems like to use Rust, you need to obsess over performance and “do things correctly.” You don’t. Full stop.

    The main benefits of Rust to me are:

    • compiler checked concurrent memory access - it stops you from writing wrong memory access
    • no traditional OOP, so you have to try harder to get into inheritance hell, but you have the tools to get most of the benefits
    • nice ergonomics - cargo, macros, etc make writing code pleasant

    Use it where you get the most value from those benefits, use a scripting language where you don’t.

    Compile times have improved, but not with proc macros

    Again, use a scripting language. In same dev, you shouldn’t be recompiling so often that this matters.

    Also, I wonder if Cranelift helps here.

    Positives of Rust

    Positives of Rust

    If it compiles it often kinda just works

    Yup, that’s why I use it.

    Performance by default

    That’s nice, but secondary to the first. In fact, I’d put this quite a bit further down my list, since performance is rarely my bottleneck.

    Enums are really nicely implemented

    Honestly, these are almost enough reason to switch to Rust on their own.

    Traits

    Absolutely, they’re another killer feature that I wish more languages had. I love being able to write relatively abstract code like:

    fn do_stuff<A, B>(arg_1: A, arg_2: B)
    where (
      A: Hash, Ord, ...,
      B: ...
    )
    

    And be able to use pretty much anything I want. That’s also a great thing about Go, I can just make an interface and use anything that implements it.

    In C# and Java, I need complex inheritance chains and to be extra careful about not writing too much in the base class that I’ll need to bypass stuff later. In Rust, I can just throw anything that fits the requirements, and even reuse random stuff from crates.io and add a couple trait impls without having to wrap it in an internal type.

    They’re really nice.

    Conclusion/TL;DR:

    I looked into alternatives, found gdnative, and then was recommended godot-rust. It wasn’t the first time I’ve seen or used Rust, but it was the first serious usage for game development, being preceeded only by game-jam-y projects.

    Since then Rust was the langauge I used for everything.

    Sounds like they overcorrected their problem (Godot pathfinding is slow) to “Rust all the things,” and now they’re overcorrecting the other way to “C# all the things.”

    It’s okay to use multiple tools to solve a problem, use the right one for the job, and have a tool belt of well maintained tools.

    What I use
    • JavaScript for UX for non-game projects - I use Tauri for my project
    • Godot for games - GDScript by default, Rust for the CPU intensive bits like pathfinding, world gen, etc
    • Python for scripts
    • Lua for non-Godot games and other apps - will probably add to my app soon once I get to stuff that needs rapid iteration
    • Rust for servers that need to be fast, Python for servers that don’t

    Anyway, that’s my take. Thanks for the writeup, I hope the helps people.