Godots signals are such a huge step up over Unity's built in classes having a lack of modularity.
How do you even make sense of that? Godot vs Unity basically have the same scene/node/component model except Godot does it better imo. Eg) What is the difference between a prefab vs a scene in Unity anyways? Basically nothing, it's just (I'm speculating) a tech debt mistake in their design, probably still going because of how light maps work today.
Unity's advantage over Godot is it's 3D renderer, built in physX, il2cpp backend for C#, profiler, general runtime performance and console support.
Godots design is objectively more cohesive, as Unity has simply splintered into 10 different design directions since ~2018.
I'm not trying to be a hater, I just think signals are a huge advantage for writing modular, simple stuff in Godot. I think there's plenty of great reasons to prefer Unity to Godot but "signals" is not one of em.
Godot is objectively a way way better tool
If you like things like Godot, Godot is the type of thing you will like.
Seriously though, Godot works way better for me using C# than it does with GDScript and the OOP structure means I can refer to classes by their identity.
I would say that. Godot is a way way better tool.
There, I've falsified your claim.
But more seriously, it's a faster dev experience, it's more ergonomic, it's not cluttered with half baked "new" ways of doing things that don't do everything the old ways do. There's no reason to pick up Unity unless you are being paid to, IMO.
> Unity's advantage over Godot is it's 3D renderer, built in physX, il2cpp backend for C#, profiler, general runtime performance and console support.
And correct me if I'm wrong, but Godot doesn't have hot code reloading where you don't have to restart your game.
Hot reloading is supported.
Console support is some work. Possible, but work.
The 3d renderer is okay, but I'm hesitant to call it good. It's not as good as Unity nor Unreal, imo.
The internal profiler really sucks.
Everything is possible if "some work". Porting to PlayStation 5 is probably a lot of work.
I'm a Godot fan boy, but we gotta be honest about its flaws.
If your targeting 3D on console, definitely go with Unity or Unreal imo.
Are signals significantly better than Unity events or is it more that the API uses them heavily?
Honestly, why doesn't Unity retool SendMessage() and public API callbacks to be an exposed Unity event? Unlike merging prefabs and scenes, that's not even a breaking change.
You don't even have to use Nodes much, though they're great for lots of stuff. For real performance, you can drop all the way down to their thin wrapper over Vulkan and do whatever you want.
GDScript is, in my opinion, unsuitable for anything more than a couple hundred lines at most.
> unsuitable for anything more than a couple hundred lines at most.
I work profesionally in ~5 code bases with ~10,000 lines of GDScript each. I think GDScript is great for UI widgets. I dont think you can say it has a 'line number' limit. It has a 'complexity' limit.
If your writing a ton of tiny little classes that do one thing (like play a sound when a button is pressed), then GDScript is probably the best language for that. Certainly c++ is not the best, and C# is perhaps worse as well. Note: GDScript doesnt need to be compiled _at all_. In unity, its common to have an annoying 'hang' every time you alt-tab from vscode back to unity, as the c# is compiled. In Godot, I can write a new UI widget directly in the editor, with no compilation hang, with hot reloading. It's simply a smoother experience for writing the mountain of basic plumbing that you write when making a commercial game. It's not all complex algorithms here, it's just a crapload of boring ass code. And GDScript is great for that.
Most of the code in games is tiny little things that manage sequences of animations. There is seriously so much small code to make a UI look and feel nice. Writing this code in GDScript is way faster and ergonomic than any other language I've used.
I agree, GDScript has many flaws, but from where I'm sitting (small studio, been in the industry for 10 years), GDScript is a massive boost for my productivity.
For complex stuff, I like to figure out the algoirithm in GDScript then rewrite it in C++ if it needs it. Works great. Again, massive increase in productivity.
It is just so confusing to me and took me over a day to get a simple menu aligned how I wanted
it might just be me not understanding how it works though
Yes, your UI will be a tree of Control nodes 20 levels deep, and that’s fine.
Your root UI node will probably be an HBoxContainer, or VBoxContainer, each of which simply arranges their children horizontally or vertically, respectively. Between those two nodes you can create 90% of UIs you’d want to.
Now I have not tried Godot so I don't know how the two compare, but for where I work Zenject was basically the a-ha moment that made it possible to develop Unity apps/games that don't devolve into a huge unmaintanable mess.
For 2D and simple 3D games, I see no reason to use Unity anymore; I predict a steady decline in Unity's market share as Godot slowly overtakes it.
While this is true it does come with a big caveat. Every single AA developer has had access not only to the Unity source code, but in some instances also to Unity employees who became directly embedded in the production cycle. There’s a GDC presentation from the team behind Ori and The Blind Forest where they talk about how some Unity devs were flown to Austria to help out with custom tooling. Playdead also has a really nice blog where they talk about all the changes they had to make to the engine in order to achieve good lighting performance/fps for Inside. https://blog.playdead.com/articles/inside_presentations/insi...
I’m sure that if the Godot foundation had enough resources at hand then you would also see more games like Cuphead and the ones previously mentioned above.
Not game dev either but I do have to say that I find Godot's design to be one of the best oop desings I worked with. I tend to not use oop much today (C++ embedded), though I did learn programming with C# so I'm fairly used to inheritance.
Working with nodes and editor bugs (or features? Hard to know really) is probably the most frustrating - you can really feel that this was initially built for 'smaller' projects.
For this reason, I rarely use the editor outside of setting up the scenes and a general hierarchy.
Daily tools: Emacs (with C# LSP) most of the time. VS Code for debugging. Godot editor for tweaking the scene tree.
Perhaps this perspective is useful for other devs thinking about Godot.
Having programmed for over 25 years now, this was my experience. I feel like a little more IDE introspection or tooling to make the signal/listener connections more manageable, is the special sauce that's missing. The event pubsub moel becomes unmanageable to document/control with any non-trivial application. Godot has no encapsulation or tracking support, allowing all modules to hook to any event leads to spaghett, which you learn when working with large projects in various languages (JS et al).
I view 3 users 1. Complete Novice 2. Engineer dabbling in games 3. Professional game designer.
For #2, they are more likely to prefer C# as they probably already have experience with it, or otherwise will be familiar with the similar Java language. Also it's a nice resume boost to say you've used C#
For #3, I can't imagine the godot language is better for large scale games than any custom language. C# just has way more resources put behind it
For #1, I kinda see it. But they would probably be better learning a language with more tutorials available. Or if they're struggling, pygame is probably a better place to start.
Unreal Engine started out that way.
The "so, you have a choice of c++ or drawing lines between boxes" is missing a lot of middle ground :)
https://github.com/godotengine/godot/issues/70796#issuecomme...
And despite my best efforts to statically type everything in GDScript, the language is full of holes that lose all the safety.
Let's say I'm not a big fan of the language. Why the hell they decided to not implement normal for loops, was just googling how to iterate an array backwards and most people were like "just invert the array and iterate over it, bro"
They should have just used Typescript, it's a sweet spot between safety and productivity.
https://docs.godotengine.org/en/stable/classes/class_@gdscri...
var array = [3, 6, 9]
for i in range(array.size() - 1, -1, -1):
print(array[i])
Admittedly not very pretty but it certainly works."why god why can't they just have for loops!?!?" and the problem was just ... knowing how to foreach over a range correctly? the idiom and language syntactical preference that python, a language older than java, has done for decades...?
Really trivializes every complaint and the assumed skill level of every person that I see in this thread complaining about gdscript to the absolute lowest level. Thanks for the post!
The doc states that range function returns an Array, so it looks like to iterate backwards you basically allocate array of indices and use those indices to get values from an original array. Not much better than reverting original array, if you will ask me.
Maybe there is some optimization for trivial scenarios, but the referred doc doesn’t mention it.
It really looks like python 2 case when you needed to remember that dict.items() returns copy and most of the time you needed iteritems().
I would imagine for most games the performance impact from this won’t matter much.
And to me it looks like pure language/stdlib problem. Like for me, the proposed solution looks ugly both from syntax and what is going on behind curtains perspective.
I would rather not to code in a language that makes/tolerates decisions like that.
Personally I’d just reverse the array and then iterate it. It’s going to make about zero difference.
Every language has its sharp edges.
I've used C# for my day job for years, but never felt the need to stop using GDScript for any of my projects.
Can you expand a bit about why this was messy or comolicated? I found the paradigm leads to pretty well organised code (sometimes you get the odd large system, but it can be broken down into smaller systems, sub systems or composed out of smaller functions).
For this reason I agree - developing games using an ECS design requires more discipline to manage complexiy, compared to an imperative one.
With regards to the chaos: I think it can be avoided, but like you said it requires a bit of discipline. I don't feel like it required that much more than normal software engineering (but I'm also the type of person that documents and tests everything even on personal projects lol). The plug-in system makes it easy to help bring order too.
This is all through a bevy-tinted lens, since I've done very little game dev (dabbled with UE and Godot) outside of bevy, though!
Easily grokable filenames and file structure are very important, and bevy specifically has a pretty nice plugin system which lets you really clearly 100% isolate groups of state/logic into more sensible sections instead of ultimately having some root level game loop that's directly setting up your 100 tiny little poorly named things.
There are two issues:
1. The fundamental issue is that the ECS model has independent subsystems communicating via a relational database. This breaks the connection between function callers and callees, makes control flow incredibly hard to trace, and means the type system can give you very little assistance.
2. Bevy also does not leverage Rust's type system in other ways. E.g. you can use resources that you forget to create and it will only crash at runtime instead of giving a compile time error.
I think you can create a good game in Bevy, and if you come from a C/C++ world you probably won't notice the lack of type safety. It didn't meet my goals, however.
Would something else even be possible in Rust? My understanding is that you cannot really add type safety in the way of "This should be a i64 and between 32 and 128, otherwise fail to compile", so not sure how it could be addressed by the language.
Or taken to the extreme "Fail to compile if the user creates an instance of this but doesn't call function F with that newly created instance"
Plugins are the main abstraction in Bevy. A plugin has two parts: build and run. Build creates stuff, and run uses stuff created by build and created by the build of other plugins running at the same time.
Build is pure side-effects, so the result type of build tells you nothing about what it builds. Therefore there are no types that can constrain what resources run uses, and therefore failing to create a resource that is used in run is a run-time, not compile-time error.
The alternative is the build returns a type representing the collection of resources it creates, and run's type is a collection of resources it uses. This requires some type level programming (a type level heterogeneous set). This is some of the simplest type level programming, but type level programming itself is quite foreign to most programmers. I assume this is why the Bevy developers went for the easier to write solution that doesn't enforce constraints at compile-time.
More generally, just like in regular programming some things are easier and some are harder to do in common type systems.
Your first example (integer constrained to a range) is harder because you need to solve linear inequations at compile-time, which is not a feature of most type systems (though see refined types).
You second example (must call a method) is relatively easy with linear types, as they express "must do something with this value".
Interesting, could you possibly share an example on how that would look like in Rust? Haven't come across it yet, and would certainly help with some things.
Lets say we want to make sure if "MyStruct" is ever defined + created, we want to make sure the program somewhere calls "register_struct" with an instance of that struct.
You can do a dynamic check to encode this, but that's not super popular. You can also issue a warning, and in theory turn that warning into an error, but it may also trigger on code unrelated to the specific struct you want it to, so I don't think that's a full solution either, and others may use your code without the warning, getting less guarantees.
Signals are basically just event subscriptions. In fact, if you use C# with Godot you can actually just use C# native delegates/events.
Godot could have built on Python, but they would have had to also include a language server (and maybe ipython or jupyter or something) to get the full seamless experience that GDScript gives. Including all that seems a bit much.
So, like you, I appreciate GDScript and have sympathy for why it was created.
Also, GDScript hasn't done anything like implicit type coercions (see JavaScript) and so GDScript can improve without breaking backward compatibility. If needed, breaking backwards compatibility in GDScript won't be as bad as breaking backward compatibility in a real programming language, so they can steer it where it needs to go for the benefit of Godot.
https://github.com/ensisoft/detonator
It's a (2D only) game engine I've been putting together for years and obviously not yet at a level comparable to Godot, maybe more like haxe or lowe2d.
The target is simple single player, single developer "weekend" games.
Having gotten into Godot with v4, it was a huge breath of fresh air coming from Unity and Unreal (which isn't really hobby friendly).
Composition of nodes is quick, easy to compartmentalize, and having signals as an interface makes building them very, very quick. Yes, the debugging story on Godot isn't quite there yet, but I genuinely doubt I'll ever touch Unity again unless I have to for a job.
- Bevy (Rust ECS engine), which is nice at first but has a lot of problems with its implementation and can become rather messy. I think it's heavily dependent on the game. Part of it will be my own incompetence.
- Unity. IMO the system of gameobjects with composed modular components is the most utilitarian - it gets out of the way, and it's easy to avoid spaghetti without requiring a really strict engine-dictated structure.
- Godot. I hated it. All of the awful heirarchy of OOP, a really poor builtin language, and "signals", which are meant to decrease spaghetti but only increased it for me. Maybe I was using it wrong? I very rarely use inheritance to the point of being bad at using it.
- Pygame, back when I first learnt to code. It's quite nice for small projects - it's procedural at heart but you can make your own OOP or functional layers over it. There have been some surprisingly large projects made in it.
I don't know Clojure, but it's interesting to see someone make a functional implementation of something that stereotypically seems like a good fit for OOP.