Article reply “Godot is not the new Unity” from Juan Linietsky (BDFL of Godot)
gist.github.com
gist.github.com
Raycasts are the most commonly used spatial queries in a 3d game. Hopefully this discussion will lead towards this issue being resolved.
I actually found Sam Pruden's complaint a bit odd since it sounds like he's developing a 2d game. If you're spamming 1000s of raycasts per frame for your 2d game, there's probably something else going on...
Yup .. but maybe not stupidity, but rather a non generic game.
In my case I need lots of raycasts, to determine what exactly the player and the enemy bots can see. Basically I have a simulation in 2D (using box2d directly in js as a wasm libary) - and all the bots and the player only (mostly) get information based on raycasts. They have to scan the world and react to that information, which leads to a different result, than the usual approach (cheating). So I am looking forward to get this fixed asap as well and also cannot really consider godot before that.
Edit: performance problems with raycasts I had to experience as well, because the roundtrip js to wasm is expensive. I first wrote a WebGPU shader doing only raycasting in my world, but better was modifying box2d (and compiling to wasm) to include a function, that does all my raycasts in one call and returns a big array (or rather a array with pointers to the structs in the internal wasm heap).
And it works already the way I want it. It could just be more performant, so more details and realism would be possible.
also, sounds like you're using JS, not Godot?
Also consider whether 360 rays is really needed to begin with, one ray per degree sounds like an arbitrary first-pass value. Can you cast a smaller set of rays first, and only cast the in-between rays if certain conditions are met (e.g. the initial rays hit something close, or their hit distances vary significantly)
Yes I can do this. But my case is really special as in basically the players have to do this by themself. As it is (also) a hacking game, meaning they have a limited scan budget and need to figure out to spend it the most useful for their bots.. but since they also want to evade projectiles and other bots, they want to scan as much as possible to not miss a threat.
So it works the way it is. Just would scale better, with better raycast performance.
I probably should have hinted more above, why my case is really special, but that was kind of my point, there are always special cases. And I do not want to limit my design, because of a bad raycast implementation.
It sounds like you are trying to query every angle in every direction for every character. This is madness.
I have a 3d space game in Unity which uses raycasts for navigation. Each ship fires a maximum of 1 navigation raycast per frame with a sweep pattern. In addition there are anti collision thrusters placed around each ship which fire roughly every second in a staggered pattern to prevent ships from getting stuck
In my fully 3d game, that's effectively ~1 raycast per frame per enemy. To locate hostiles, each ai character scans a runtime set of potential hostiles and does a line-of-sight query roughly once every 5 seconds.
There definitely is another issue going on here with your setup that is independent of the extreme overhead in Godot.
I would recommend Sebastian Langue's excellent boids video to get a sense about other strategies to deal with these types of queries: https://www.youtube.com/watch?v=bqtqltqcQhw
It is just a different game than yours, so maybe don't judge?
Although I really like the idea of giving the player control over how the bot raycasts and letting them optimise that. Lots of fun strategies to find there! I’d even bound it so they can’t afford to do too many raycasts so they have to get creative.
This is actually exactly what I did when I built a similar game about a decade ago! Bots had a budget of 20 raycasts per second, which would slowly replenish. It was the bot programmer's responsibility to figure out the best way to use them. It was a lot of fun! :)
Is this a thing?
I've been using ammo (wasm bullet) and while wasm interfacing certainly has a mismatch with idiomatic js I haven't knowably hit a problem with that bridge.
For anything you’re doing in WASM it’s much better to batch and cross the boundary as little as possible in hot loops. For example a performant renderer wouldn’t translate all the API calls but put together a command buffer to be returned to JS and then forwarded to the API in one go.
If there are on the order of even several dozen enemies on the screen at any given time, you could simply maintain runtime sets of different factions and only do line-of-sight checks between hostile groups within a certain proximity.
There's probably hundreds of better ways to do this than by spamming raycasts. I have a VR space game with dozens of spaceships, and there are generally never more than num_spaceships raycasts getting fired every frame
Sure, I optimize what I can. But there is only so much I can do, without hurting the core game mechanic. Which is a arcade shooter, but also a hacker game, where you program your bots. So the bots are mostly limited to radar distance information by design, to work out their position in the world and what to do next (but to make this work with many bots, I already had to cheat a lot).
And it is unreleased, in case you are wondering .. but I hope to ship an alpha, soon. So it already works and it is fun. So I won't change core functionality, but I am still optimizing wherever I can. 3 months ago, it would only run on gaming hardware. Now medium mobile phones (a big market) are within reach.
Also don't need to do this every frame, do X% each tick (not frames literally), rotating which objects get their checks.
The previously mentioned case of doing hundreds of raycasts all starting in the same location but each in a different direction could be done with rasterization instead. That’ll involve a single loop over all the triangles in the world instead of one loop over the same triangles for each raycast. And for NPC vision you could rasterize billboards instead of the full character geometry. You can probably simplify the world geometry too.
That’s all I mean.
But what does any of this has to do with improving the ABI?
But as somebody working in Unity (and often on mobile), there's still many cases where 1000 of something is a lot, and should perhaps be cause to rethink your approach. For example 1000 draw calls, 1000 UI elements, 1000 instances of even the most simple prefab.
1000 raycasts per frame is also something that I'd try to avoid. But if they seemed important, you've just got to try it and profile it. Nobody can answer 'what is the cost of 1000 raycasts?' without a fair bit more information.
This approach in 3D would basically mean live raycasting rendering, which is something I would like to try in the future.
You're right that raycasts aren't an edge case in terms of usage, but Juan Linietsky's point is that the inefficient path used for this API call is a rare exception to the efficient paths used by the vast majority of the API.
I'm not sure I would have been so generous to the author of the article this is in reply to. But I suppose that's a skill of a successful open source leader -- to turn interactions with critics into productive discussions rather than arguments, and perhaps even turn the critics into supporters.
It seems to have been that author who chose the FUD-ful title "Godot is not the new Unity". I guess there are times in life where you face a choice: be fair, reasonable, and intelligent, or... just try to get them clicks.
Well, that article got a lot of click. Good job?
FWIW, reduz (Godot author) and sprudd ("Godot is not the new Unity" author) previously discussed this on Reddit[1], and sprudd was actually sounded pretty nice (the first reply even includes a "and I hope that I wasn't too rude in the article. :)").
Overall, I think the original article was written in good faith, just with a click-baity title (and I imagine reduz thought the same thing). That might have helped to avoid a more angry reply.
1: https://www.reddit.com/r/godot/comments/16lti15/godot_is_not...
For the past few days everyone is talking about Unity, and I don't think it's exaggeration to say that Godot has become the de facto alternative in low to mid level game development.
Godot itself will (if not already is) benefit from that status a lot. Article that brings highlights parts well Godot is lacking compared to Unity is perfectly valid criticism to have.
And that's because the author didn't even touch the "in-app" purchase and "in-app" ads capabilites from Godot x Unity, which is the way the studios complaining about the new Unity pricing, generate their income..
I do think the original article's claim of 'Godot is not the new Unity' is accurate, just not for the architectural reasons claimed. Folks probably shouldn't go into it thinking that Godot will handle every use case just as well as Unity. It hasn't had billions poured into it like Unity, but it is mature and ready for serious games. Plus - open source means you can just get your hands dirty and fix critical (for you) bugs instead of hoping Unity gets around to it.
I feel like this entirely disregards the caching costs of using >2x more memory in some cases, speed of float32 vs float64 operations on CPU, and potential CPU <-> GPU memory transfers.
EDIT: Nvm disregard this comment, I just noticed the existence of: PackedByteArray, PackedInt32Array, PackedInt64Array, PackedFloatArray, PackedDoubleArray
Anything set of numbers needed by the GPU or big enough to affect the cache will probably use those arrays.
How do you figure? Are you saying there should be no tight loops that hit engine code, none that live in the C#/scripting lifecycle or all tight loops should be rewritten in C++?
The elephant in the room, Unity, cross compiles the C# to C++ which makes this blanket statement about all games even more confusing to me.
As a game developer you do not have access to Unity's C++ code so to maintain some performance Unity needs to do that. But this is not the case with Godot or even Unreal where any intensive code should be written (or at least, rewritten) in C++ and use the scripts only to drive the behavior.
But saying 'oh you shouldn't use the nice language anyway' is just making excuses. Obviously they're meant to be used to call engine code.
Hearing people dismiss the performance of something as basic as a raycast with "well just code in C++", while many people (including this founder) say that Godot focuses on simplicity sounds counter-intuitive. So is GDScript a lie for anything slightly intensive (and again, raycast. I'm using "intense" in the loosest of words) and I should simply make my whole game an engine module? But I keep hearing that "I should just try GDScript it's really easy and you come around to it!"
Feels like a motte and bailey.
There is nothing counterintutive in that, it is right in the name of scripting languages: they're meant to script behavior.
And the dismissal isn't about having a raycast being slow, but about using too many raycast queries in script to do something reusable that should be in native code in the first place. If your scripting language ends up in your performance profile chances are you are using it wrong.
The occasional raycast query in scripts to make a decision is fine, doing thousands of individual raycast queries from scripts is not - if nothing else, make an API that accepts multiple raycast queries at once, performs it in C++ in a single call (so you only get the scripting overhead for that single call) and gives the result back.
But IMO if, as mentioned in the article, you are going to make a controller that is to be used by multiple entities in the game, then you should make it in C++ - potentially with script hooks to customize the behavior, if needed.
You may even invert direction, handing over a pure script language function (no context) + the data, so the c++ engine may crunch the data at least in parallel small script vms without stack, similar to a shader.
Here's a good example (look, there I am!), although it's a bit old and actually led to perf improvement:
I’m a fan of making everything 64bit from an api level, but sometimes you have to work with the right type for the architecture.
Godot is better than Unity on many sides, but the internal architecture is coming from a place where they relied too much on naive and inefficient OOP constructs, those can be very hard to optimize later.
Performance should not be treated as a second class citizen when creating an engine, there are always solutions but it can be very time consuming to find workarounds to palliate design issues with the engine, it can also be a real motivation killer for a small team when they discover the framerate of their game on older/smaller devices...
This particular discussion focuses on the performance gap between the two engines looking specifically at how raycasts are implemented, and the larger implications from that analysis.
Yeah but you have a 32 bit data type and a packed 32 bit array, so why not have the same for 16 bit? Not just that, there are also SIMD operations that work better with 16 bit numbers.
Once you can press a button and get Win/Mac/Linux/Android/iOS/etc versions of your game built, you're in business.
All the higher-level features (3D, ray casting, etc) will be contributed by the community over time.
I believe the issue was less with the sizes of items being passed in and more with the API conforming to work with GDScript first and formost. Returning a dictionary for an operation that has a few float64's feels overkill and doesn't make sense even with an explanation of the available datatypes.
>Only a pathological use case is shown, the rest of the API is fine.
I wouldn't call raycasting in a full blown engine "pathological". Especially one that touts 3D
Secondly, that doesn't inspire confidence. "Don't mind the room on fire, the rest of the house is fine!". The onus is on the engine to prove that, and numbers prevail over words. So far only one part of the conversation has shown that.
Even in the next sentence it sounds like they focus on a simple API over performance, and that doesn't fill me with confidence. If Godot isn't focusing on 3D, that is fine but there's so much noise trying to to say otherwise
> Eventually, C# will be moved to the universal extension system and this will allow the unifying of the default and .net editors, it is just not the case yet, but its top in the list of priorities
I hope so, but there seems to be a trend of various "top priorities" from Godot that have trouble crossing the finish line. That's a reocurring issue even in this response alone: I'm not convinced that performance is a top priority for Godot. And that confidence means everything if the "BDFL" controls what gets into the project proper.
>The problem is that, at the C++ level, this function takes a struct pointer for performance. But at the language binding API this is difficult to expose properly. This is very old code (dating to the opensourcing of Godot) and a Dictionary was hacked-in to use temporarily until something better is found
Yup... so 10 years later that hack stays in and modern programmers come cross it.
This isn't even a critique, that's simply the nature of legacy code. Unreal has an entire part of a forced namimg scheme (the compiler won't let you run the game without conforming) that can only be explained as "well we wanted to do this in the 90's but we slowly took it out sp it's not relevant today". But if it took 10 years for someone to do more than a few dozen raycasts a frame, it says more about the battletesting than any deep dive. It goes back to my confidence above.
>, you need to create a C# version of a C++ instance as an adapter... Why is it troublesome? because C# has a garbage collector and C++ does not.
slight nitpick: while garbage collection is annoying, you technically do have a built in way to disable it in certain regions, as well as the option in later versions to have unmanaged blocks of code. I'm not saying this is easy to do, but it is something that developers much smarter than me in c# have gotten around. I know c# bindings was a relatively recent endeavor so I'm not going to give it too much flak
> Godot containers don't work like STL containers. Because they are used mainly to pass data around, they are allocated once and then kept via reference counting.
1) reference counting implies some sort of automated memory free-ing scheme. 2) That doesn't necessarily address potential issues of inefficiently allocating memory and keeping it contiguous. But I won't talk much on that because I'd need to first read more on the engine's memory allocating schemes first.
> Godot uses far more optimized containers that are not directly exposed to the binder API.
Okay, but why? Someone wanting to use C# or c++ or whatever script extension that isn't GDScript wants those optimized containers. Does it go back to the earlier quote of "it's difficult to get right and no one wanted it"?
>As a result, we created a special path for GDScript to call more efficiently.
okay, and the link is... an open issue on Github made 2 months ago, with no additional comments or discussions. Simply a request from a code owner.
I don't know if this conversation is simply happening in IRC/chat, but it's unusual given how much other activity I have seen in other PR's/proposals (recent and from years prior). Was this the best reassurance that they are addressing performance?
---------
I don't mean to sound like a downer, but I feel the article is overall missing the forest for the trees. I've read about several different kinds of devs from years prior talk about how they passed on Godot because they hit hitch after hitch once they were doing something slightly advanced. a dismissal of "this is a pathological use case" sounds fine in a vacuum, but it sounds like this has been a long standing issue, and priorities simply weren't on smoothing out such hitches.
I'm not saying they should have listened to those devs, but I think the most frustrating thing is that I don't know what or who Godot wants to service. So far it sounds like they want to have all the cake, but currently are also low-key fine being a hobbyist 2D engine that can maybe do some simple 3D stuff. Which again, is fine. But that's not what it sounds like Godot is selling. It unfortunately reminds me a lot of Unity, both on the outside (yeah, having 2 unsupported netcode solutions with a 3rd in pre-alpha isn't a good look) and within the company itself. I'll quote some part of a post from the creator of Rimworld, who had similar evaluation and conclusions over 5 years ago:
>There's obviously a tremendous amount of technical talent going into Godot, but from what I can tell there's no strategic thought about market positioning or success pathways or goal pillars at all. It basically comes down to "make a good game engine", with all the lack of boundaries and lack of focus that implies.
>My initial thought: Be best at one valuable thing first, then expand out from there into adjacent domains, using the momentum accrued from the initial success. (e.g. If you want to build a restaurant empire, you start with one restaurant to dominate one neighborhood and then expand from there - you don't try to build 100 restaurants at once).
Personally, I find this a refreshing admission.