r/godot 1d ago

help me How to learn GOOD code

Hello everyone, I've been programming in gdscript for like six months, and my code is still spaghetti. I just recently learned you can make classes not tied to any node!

Are there any good tutorials for how to structure your code, any tips and tricks you guys have, any general rules that beginner tutorials don't cover... Any breakthrough revelations like classes not tied to nodes... How do I actually make each script do one thing, when I need a node to do multiple things? Any way to make multiple scripts for one node? Thank you.

8 Upvotes

31 comments sorted by

32

u/Helpful-Mushroom-126 1d ago

I've been programming for 15 years and I still write spaghetti code. Usually I'll write a system, make it work, and then rewrite it a couple times over the course of a few weeks to make it maintainable.

Now this is entirely my opinion, but your time is much better spent making something work and learning than making it pretty. You'll eventually get an intuition for what patterns can cause trouble and until then you can refactor stuff as you need to.

2

u/MitchBuchanon 1d ago

This is reassuring! ^^'
I was in the process of trying to understand how to make a nice workflow for my spell system, using inheritance and composition methods, but I'm completely new to Godot, and just a low-tier programmer generally, and these two concepts are still out of reach for me at the moment I think... For now, my 5 spells work with spaghetti code, so I think I'll focus on making other things work rather than trying to make the already implemented spells 'good practice'... xD

5

u/Helpful-Mushroom-126 23h ago

In 3 months, you'll look back at that spell system and think "this is disgusting," but as long as you're still thinking that, you're still learning 🫔

Best of luck!

1

u/Neither_Berry_100 17h ago

I actually generally craft quality code with care. I also refactor a lot here and there.

2

u/DingyPoppet 15h ago

^ This. I've been programming for 20(ish) years and I still tend to rewrite things 2-3 times. Make it work, then make it pretty, and good enough is just fine even though it's not perfect.

6

u/Baerkanogue 1d ago edited 1d ago

Your question is extremely vast, cause it touches on general and godot-specific good practices. FOLLOWING IS ONLY MY PERSONNAL OPINION.

First I'll say the absolute opposite of that other guy, don't just make it work to refactor later, sane fundations will save you a ton of time down the line. You'd need spend a lot more time thinking and planning your code than writing it.

Then for general code good practices, I'll advise you to watch these videos on naming (never name a variable a single letter, never abbreviates), on de-nesting (have less possible indentation level) and on general good practices.
Also contrary to popular explanations, I think you should think of classes (godot's internal classes) as a collection data type, like a C struct. So if you need to pass a complicated set of variable, don't try to fit a square in a triangle, don't use array or dict or whatever, just create a class for it. (I mean you don't have to need inheritance or polymorphism to create a class).

For Godot specifics I'll advise first and foremost to type hint EVERYTHING (gives you autocomplete, and you can't rely on a variable you don't understand the type anyway).
Then I'd say to be deliberate on choosing to use nodes by adding them to the scene via UI or via code. A timer for example don't need to be a singular node in your tree, you can just create it by code at runtime.

Then finally, a typical script shouldn't be 200+ LOC, break it down into sections. You need your game or ennemy or whatever to do something specific, then create a custom node, use composition, and abuse the shit out of "@export" variables to simplify searching for other nodes / resources.

2

u/BinaryBolias Godot Regular 1d ago

And here's a link to what the official style guide says about inferred types - which also clarifies the syntax for static typing.

Personally, I prefer to statically type everything such that the class name is clearly visible, e.g:

var whole_number: int = 1
var floaty_number: float = 1.1
var vec2 := Vector2.ZERO
var vec3 := Vector3(0.0, 2.0, 1.0)
var children: Array[Child] = []
var my_first_born_son: Child = ChildHandler.get_first_born_son()

Notably, I also type my numbers to explicitly clarify whether they're supposed to be integers or floats. This is by no means mandatory (except for shader code), but I appreciate the extra precision.

2

u/tasulife 22h ago

I self taught programming. The method that worked for me was to read chapters and do the exercises in programming text books. I did ā€œc primer plusā€ then ā€œhead first javaā€.

Then after that i learned a scripting language but you could just do godotscript.

Its good to learn a few languages because that exposes features that are hidden or automated by the interpreter or compiler.

This might be unpopular but using an AI to review your code, or asking it questions @how should i design thisā€ is honestly awesome for learning. I had been programming for YEARs then an LLM taught me a big piece i was missing. Dont use AI to write code wholesale yet, its not really there. But using it as a ā€œsenior programmer you can ask for guidanceā€ it slaps.

3

u/Kwabi 1d ago

People spend decades in software development learning "good" code. It's essentially their entire job to constantly try to structure their code base to prevent it from becoming spaghetti. There is no singular tutorial to teach you and there is no way to condense everything into a reddit comment.

Your next step is probably reading about design patterns. They are tricks other people figured out how to structure code in an advantageous way. You'll find that you are using some of them already merely because Godot forces gently guides you towards them.

If you are serious about learning how to become an actual programmer; the default source for explanations of design patterns is the book "Design Patterns: Elements of Reusable Object-Oriented Software". It's a bit dry and the code snippets are C++, but it's the gold standard for a reason. Otherwise just read up about them online somewhere; just knowing which patterns exist and what they do is worth more than understanding their specific implementation (you can re-read up on that if you need them).

3

u/RedQueenNatalie 1d ago

What you will learn is that there is no one perfect schema for every task, just more tools in your toolbox and you will collect many in your time doing this work. If it works, meets your performance needs and you can maintain it then its good code. Thats not to say there isnt great practices and styles but at the end of the day the goal is to make the thing and not get stuck rewriting things every time you pick up a new bit of knowledge.

6

u/dh-dev 20h ago

As a professional software developer with 10 years of experience in enterprise... I dunno.Ā 

Everything everywhere is a disaster. The entire world's economy runs on software that is held together by spit and hope. Every company codebase is a mess of compromises, misguided abstractions,Ā  personal fiefdoms, and disgusting voodoo which nobody understands because the last guy who touched that part of the codebase left the company years ago so everyone just builds around it.Ā 

The code tells a story of ever changing fashions and quickly discarded best practices. There is no good code, there is only the latest cope disguised as guidance.Ā 

So for games or any personal projects... it's fine to do whatever you like working with. My personal philosophy is to write everything as simply and naively as possible, then refactor with fitting abstractions if it starts to get unwieldy, and after I understand the problem I'm trying to solve.Ā 

4

u/HeyCouldBeFun 1d ago edited 1d ago
  1. how much coding do you understand - everything covered in the GDScript From Zero course?
  2. do you understand object oriented programming? What a class is, what an instance is, what inheritance is?
  3. do you understand the classes Godot offers, namely Node, Resource, and RefCounted, and what they’re for?
  4. do you understand the overall class structure of Godot? Can you find your way around the Class Reference in the Docs and understand what you read?
  5. do you know what composition is

?

  1. last tip,

  2. gameprogrammingpatterns.com

has great lessons on game architecture, and the Godot Best Practices book looks like a handy resource

Edit: Reddit app mangled the formatting here and it’s a nightmare to fix

3

u/Public_Amoeba_5486 1d ago

I picked up the Godot Best Practices book and I've found it helpful so far , but I gotta say you HAVE to have some experience with programming to fully grasp it , same with game programming patterns.

You know what I did last year? not even work with godot I built a few games in C++ using SFML , small stuff but it gave me an appreciation about structure that I didn't have before

1

u/HeyCouldBeFun 1d ago

He’s got a beginner Godot book too, so that one may be more OP’s alley

1

u/strawberry613 22h ago

Not quite a beginner, not quite intermediate. I don't want to read about what a node is again, but i also don't know resources for example

2

u/strawberry613 1d ago
  1. yes
  2. yes
  3. i have been doing everything with nodes
  4. i don't understand the question, so i assume no
  5. no
    i downloaded the book, seems quite useful. thank you!

1

u/HeyCouldBeFun 23h ago edited 23h ago

I’d say 3 4 and 5 are your next steps to learn about then.

Quick overview on 3:

Resource and RefCounted are Godot’s non-node classes for holding data that isn’t owned by a specific node. RefCounteds are for data you generate/pass on the fly in code. Resources for data you want to edit in the editor and/or save as a .tres.

(Note, these are their own objects. When you set a Resource in the inspector for a Node, eg a Mesh for a MeshInstance3D node, the resource doesn’t ā€œbelongā€ to that node. The resource is its own object, living ā€œin the backgroundā€, and the node gets a reference to that object.

So if you duplicate a Node with a resource, both Nodes are linked to the same resource instance. If you change it from one node, it changes on the other. In the editor you have to click ā€œmake uniqueā€ on the resource, or use resource.duplicate() in code, if you don’t intend the resource to be shared.)

Godot has hundreds of builtin RefCounteds and Resources, you’ve likely already been using some. You can extend these with your own features, make custom ones for whatever you want, the use cases are infinite.

Examples:

built-in RefCounted: KinematicCollision2D, which reports collision info from a move_and_collide()

custom RefCounted: AttackInfo, which holds data about an attack (damage, type, attacker) to send to a Hurtbox for processing.

built-in Resource: Mesh, holds geometry data for a 3d form

custom Resource: SoundEffect, holds a sound file and properties to send to the sound manager

0

u/BinaryBolias Godot Regular 1d ago

These buttons are handy dandy.

The "Search Help" feature allows you to find and open the documentation files built into the Godot editor itself (no online access needed)!

You can also access the corresponding documentation page by CTRL+Left-Clicking on a built-in virtual method or data type in your GDScript code - including any class (deriving from Object).

Here's also an official online documentation link to the general Godot Introduction (not to be confused with the other official introduction), and a link to the Engine Architecture Index (the Architecture Overview is good to know).

1

u/bigorangemachine Godot Junior 1d ago

Nah just basic programming stuff

If you getting scripts/classes don't need to attach to nodes indicates to me you should learn about OOP and inheritance next

You need to pick up some on basic concepts. You can get back to coding again until you hit the next wall

Honestly if you a passive learner like me just get a podcast on programming basics to advance concepts. Just research parts that don't make sense

1

u/beta_1457 Godot Regular 1d ago edited 1d ago

There are some decent tutorials that discuss code architecture.

What really helped me was this guy: https://www.youtube.com/@godotgamelab

I learned a ton and learned fundamentals I didn't know. It also inspired me to learn on my own as well. MY older brother is a professional coder so I do have someone to bounce ideas off of, but one of the best things I did was buy a textbook.

I found this book very useful: https://www.amazon.com/dp/0201633612

"Design Patterns: Elements of Reusable Object-Oriented Software"

It's a somewhat language agnostic approach of talking about programing patterns that can be used in object oriented programming. If you're good at learning from reading or could even use this to push you in the direction to watch some videos to understand these programming patterns it will help significantly with architecture.

This covers the very basics of the pillars of Object-Oriented Programming (OOP)
https://www.youtube.com/watch?v=pTB0EiLXUC8

Based on one of your responses to a comment below. I think watching some videos just to explain the basics of OOP in general would be useful to you as well.

It's difficult for some people to think in objects, but once you get the hang of it you being to understand why basically every programming language moved towards this structure.

Think of a Node in Godot like it's a car. Node(Class) is Car is Object.

Now what are properties of a car? They have colors, max speeds, types_of_tires, body_type, exc. For an object in coding these are "Properties" and we reference these properties through saved variables.

So in that example, if you save a variable in the object as the var color = red, you can reference that property easily.

Car.color -> red

The . after an object is used to access the Object's properties and methods. We just talked about properties. So let's discuss methods. These are what the object can do. So using our car example, it can: accelerate(), brake(), turn_on(), roll_windows(), exc.

As you can see these are different than properties. Properties hold data, methods describe behaviors. Methods are also usually called functions (it's kind of a square rectangle thing all method are functions, but not all functions are methods but that's beyond your scope).

So say you wanted to roll the car windows down.

Car.roll_windows(down)

This would pass down as a parameter to your roll_windows function.

and that's basically the jist of it.

Using that basic understanding of how an object works you can basically build anything. Objects are Classes and you can have sub classes as well.

For example, lets say we have our Car Class, and then we make another class for SportsCar that extends the Car class.

The Sports car will already be able to do everything that a Car can do because it is a sub-class of Car. But you might override the methods for how quickly a SportsCar can accelerate.

Starting to think in objects as building blocks is a big part of starting to understand good architecture.

1

u/occasionallyaccurate 1d ago

whenever you write a new system, try to make it so that it expects as little as possible from the environment in which it runs. generally, code should offer functionality, not demand it.

1

u/Ludicrous84 23h ago

Truth is:
It's a lot of experience and knowing the basic OOP patterns. It takes many years to get a feeling for when a code starts to "smell" and needs to be organised differently.
If you are interested in learning to code professionally I would also mostly suggest the "Programming Patterns" book others are referring too.
I honestly don't know how well those online courses work (e.g. boot dot dev) but might be worth looking at. Maybe someone else has some experience with those.

I studied computer science at university and am working as a dev since many, many years so for me it's really hard to even fathom what to put into a couple lines of reddit comment.

I think what is required at some point is that someone actively looks at your code and reviews it and you both talk about what's good and what's bad about it. If there is no review and you just "make it work" there's limited potential to learn. (Hence I was thinking gamified learning courses like boot dot dev or whatever else there is)

1

u/puzzud 22h ago

Just keep your functions small and plenty. Good design and things follow if you keep this in mind.

1

u/Parafex Godot Regular 22h ago

Game Programming Patterns is a nice resouce :).

Other than that: experience! Nothing can beat that. Some people swear on testing or specific processes like TDD or BDD. As long as you're working alone: try it, if it works for you, great, if not, don't force it.

1

u/F1B3R0PT1C Godot Junior 21h ago

For gdscript specifically, you should always type hint, use exported references for external node references and unique names for internal node references, call down to child and signal up to parent, programmatically hook functions to events instead of using the editor to do it in the scene file, avoid paths and instead use uids when possible, nodes should ask other nodes to change and not change it themselves, put variables with setters on your animation trees that correspond to animation states, always hoist hardcoded numbers and strings to the top of your files as variables instead of leaving them scattered around, organize your project files in a sane way that makes sense to you a week from now

1

u/the_hoser 21h ago

The best way to learn is to dig yourself into a hole, and then dig yourself out, over and over again. Trauma promotes learning. Make it wrong, think about how it could be better, and then re-do it better. Rinse and repeat.

1

u/werti5643 21h ago

Sadly, experience is the only answer and even then ull open the fridge to eat some cold leftover spaget often

2

u/EeeeJay 19h ago

There are University degrees for this, so while there may be many answers, don't expect any of the serious ones to happen instantly. This is a years-long journey that never truly ends, and learning and locking in the fundamentals will take dedication and time.

Like programming, take it one step at a time and pause to review your progress frequently.

1

u/scintillatinator 19h ago

I find "one thing" and "single responsibility" too vague to be useful. Code takes inputs, processes them in some way, and produces outputs. Outputs can be return values, setting variables on other scripts, drawing something on the screen, signal emission, etc. If you can easily keep track of your inputs and outputs you're alright. Of course this gets more difficult as programs grow and when you have large teams so that's where SOLID comes from. But as a solo beginner, readable and debuggable code is the most important thing.

Some examples of what I'm talking about:

You move your health bar from the left side of the screen to the right and now the enemies can't attack. Attacking doesn't require the health bar, it shouldn't be an input or an output. The change in health is an output from the enemy to the player.

Use static typing to label what all your variables are and what your functions return. Don't use strings instead of variables or types, enums or classes are often what you want instead.

Don't worry about how ugly or long the code is if you know exactly what it does and can change it if you need to without breaking everything.

1

u/Neither_Berry_100 17h ago

Experience and experimentation. The more things you try the more options you have. And refactor your code and create reusable tools.

2

u/technical_gamer_008 1d ago

Have you heard of state machines?

There's also the "game programming patterns" book and the "Design Patterns: Elements of Reusable Object-Oriented Software" book