Comment by fidotron
9 months ago
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).
YMMV, but I find C# and TypeScript to have a "Goldilocks" mix of OOP and FP that you can take advantage of the strengths of each where it makes sense.
You’re absolutely right, they are incredibly pragmatic.
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.
>Much of the anti-OOP noise is the result of people that have suffered from others creating hierarchies of the world too literally.
I think one of the problems is that a heirarchy is inherently opinionated. You have to choose the criteria around how to group the objects/nodes in your graph and that criteria is context-dependent. The example I've used with animal taxonomy is grouping your objects via things you can eat vs things you can pat. Thsoe are two very different graph structures of the same group of objects and if you started with one then realized you need to change, how you use your objects you're gonna have a bad time. Multiple inheritance is the bandaid solution that usually comes with more hassle than it's worth.
Building a UI is a good example of a heirarchical structure where you know exactly how you want to use your objects and how they'll relate to each other, Not having access to that programming structure would be frustrating and just feel like a loss. But I've also done multiple large refactors of Python projects because I relied on OO inheritance models that turned out to not be quite the right implementation. In those situations, Rust traits are a breath of fresh air for offering the right kind of polymorphism.
I shall recommend this talk for you https://www.youtube.com/watch?v=rX0ItVEVjHc
Funny how at the end of the talk a senior looking guy asks him, “Why not just use C?” and the speaker basically admits that that would be his choice but for “cultural” reasons.
2 replies →
I love a long, deep-dive, nerdy talk like this! I'll check it out, thanks.
> OOP is a great way to model the world
There's a reason Simula was the first OOP language.
https://en.m.wikipedia.org/wiki/Simula
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!
Yeah, that bifurcation makes practical sense. Have you considered WebAssembly for the game script layer?
1 reply →
Isn’t the trait system exactly the way out of this tar pit?
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.