T O P

  • By -

AutoModerator

**How to: Tech Support** To make sure you can be assisted quickly and without friction, it is vital to learn how to asks for help the right way. **Search for your question** Put the keywords of your problem into the search functions of this subreddit and the official forum. Considering the amount of people using the engine every day, there might already be a solution thread for you to look into first. **Include Details** Helpers need to know as much as possible about your problem. Try answering the following questions: - What are you trying to do? (show your node setup/code) - What is the expected result? - What is happening instead? (include any error messages) - What have you tried so far? **Respond to Helpers** Helpers often ask follow-up questions to better understand the problem. Ignoring them or responding "not relevant" is not the way to go. Even if it might seem unrelated to you, there is a high chance any answer will provide more context for the people that are trying to help you. **Have patience** Please don't expect people to immediately jump to your rescue. Community members spend their freetime on this sub, so it may take some time until someone comes around to answering your request for help. Good luck squashing those bugs! Further "reading": https://www.youtube.com/watch?v=HBJg1v53QVA *I am a bot, and this action was performed automatically. Please [contact the moderators of this subreddit](/message/compose/?to=/r/godot) if you have any questions or concerns.*


Exerionius

Can't you just use `get_nodes_in_group()` for your goals?


Dookie_Loops_Bedroom

That works, thanks.


Alternative-Signal30

The get\_nodes\_in\_group() will definitely work, but in the future I take the never nesting approach. Instead of saying if something: if something_else: if another_something: Put logic here Do if not something: return if not something_else: return if not another_something: return Put logic here It ends up being longer vertically but much more readable in my opinion. Sorry for format, doing this on my phone Edit: Attempting to fix format


Buffalobreeder

[This is a great video explaining this concept](https://youtu.be/CFRhGnuXG-4?feature=shared)


Alternative-Signal30

This is the video that got me to become a never nester. I'm not perfect, but I always go back to refactor if something is nested more than 2-3 indents deep


DatBoi_BP

Extraction is also nice because it naturally makes unit testing very modular and specific


According-Code-4772

Do you mind elaborating on how this would be done when you have nested for-each loops, each nested iteration using the current value of it's parent loop, like OP has in their code? I see what you mean if it was just nested if statements, but confused at how you would do this with what OP is showing in their screenshot.


ImpressedStreetlight

I'm not sure if I understand, it's exactly the same concept: ``` for node in get_children(): if not node.is_in_group("group"): continue for child in node.get_children(): if not child.is_in_group("other_group"): continue for spawner in child.get_children(): # do stuff ``` Nesting the for loops is unavoidable, but not nesting the conditionals gives you much more horizontal space and makes it more clear to which loop each line belongs. PS: although I would argue that sometimes nesting conditions *is* more readable. I just do what seems better on a case-by-case basis. No need to blindly follow an arbitrary rule.


Brickless

you can only reduce the first if. the other two are non excludable. your approach would either not iterate over „Doorways“ or would iterate over them as if they were „Spawners“ putting these loops into their own functions or creating arrays to store filtered results would be the way. however I am not in any „never“-camp so I am fine with just removing the one if, before looking in the documentation for a better way


ImpressedStreetlight

Yeah, in the case of having to do different things for two different conditions it doesn't make a lot of sense to write it this way (at least regarding readibility).


According-Code-4772

> although I would argue that sometimes nesting conditions is more readable. I just do what seems better on a case-by-case basis. No need to blindly follow an arbitrary rule. Yeah, this was pretty much my thought, and that here specifically it was actually less readable never-nested, or at least any method I would consider would be in my opinion. The person who made the comment I was responding to explained [later down the chain](https://www.reddit.com/r/godot/comments/1dizyik/is_there_a_less_obtuse_way_to_iterate_through/l98d75l/) that they agree alternatives for the code actually posted are less readable and they were more just giving a general recommendation, which makes more sense.


Rustywolf

the real answer is that you move subsequent logic to a different function as to "reset" the indentation (The theory being that if your code is too far indented it means that your function is doing too much and should be split up into smaller chunks to make it easier to read)


Alternative-Signal30

You could use a recursive method for something like that. An example would be So basically if you needed to do something like in your example you could write something up like this and this would iterate through every single node from the original provided all the way down. Use whatever logic you want in place of [node.name](http://node.name), or even the recursion method itself but this is the gist. There are lots of different ways to design algorithms with this. Be Warned though that recursive methods need an escape clause or else they can infinitely call themselves and you end up with a Stack Overflow Exception. \* Edit to add another method of doing it Additionally you could use multiple functions if you have several processes that differ too much to put into a single function for example func i_do_one_thing(node: Node): for node in node.get_children(): if not something_i_decide: continue i_do_two_thing(node) func i_do_two_thing(node: Node): for node in node.get_children(): if not something_i_decide: continue i_do_three_thing(node) func i_do_three_thing(node: Node): for node in node.get_children(): if not something_i_decide: continue i_do_three_thing(node)


According-Code-4772

> So basically if you needed to do something like in your example you could write something up like this and this would iterate through every single node from the original provided all the way down That is not what the code that OP posted does though, it does specific groups only at each level. Your method would result in more nodes being processed than necessary, potentially many more depending on the scene tree. Also feels a bit counter to the want for improved readability, IMO at least. I was also more curious about a general nested for each loop situation. OP's situation happens to be one where each level wants the same property (children) but that often isn't the case for nested for each loops in my experience.


Alternative-Signal30

Not necessarily. I got a little lazy and used a comment, but they could use an escape clause at the beginning to check if the groups exist like so `func i_do_things(node: Node):` `# Maybe return if the node is not in groups Chunk, Spawners, or Doorways` `var has_desired_group: bool = false` `for group in node.get_groups():` `if group in ["Chunk", "Spawners", "Doorways"]:` `has_desired_group = true` `break` And if this doesn't fit their exact needs at least it's a tool in the toolchest, especially since the question was looking for less obtuse ways of doing something.


According-Code-4772

So I fully agree with the want to improve readability, I guess my main question is just is that actually less obtuse? I'm familiar with the video that was linked, and in situations like what that shows it definitely makes sense, but even that video mentions that there's limits to where it is applicable. It also mentions part of the want is to make it clear what's happening in the main function, which I feel OP's code is pretty clear that "chunks" contain "spawners" and "doorways", and specifically those 2 will have connections created depending on which of those 2 they are (or both if part of both groups), while the alternates seem to make it less clear what's happening. Nothing against the recommendation in general, and I do typically code the way the video shows, was just surprised to see it given the code OP presented and was mainly wondering if there was some other method that I was unaware of.


Alternative-Signal30

>It also mentions part of the want is to make it clear what's happening in the main function, which I feel OP's code is pretty clear that "chunks" contain "spawners" and "doorways", and specifically those 2 will have connections created depending on which of those 2 they are (or both if part of both groups), while the alternates seem to make it less clear what's happening. I agree that for this specific use case it does make it less clear, but since we're talking about iterating through nodes in a tree in the original question I find that each of these methods has use cases to make things less obtuse. This has been my experience with all of these methods at least and I wanted OP to have options going forward. Teaching to fish vs giving them a fish and all that.


Lilixer

I was taught to only ever have a single return statement in your functions. Wouldn't these two methodologies conflict or was I taught wrong? It was from an old professor that used to program for satellites so the code needed to be absolutely failsafe presumably.


StudioLapiku

Early returns are absolutely used in production code at reputable firms! Short circuiting code execution is a great way to save on time and costs, especially if you are skipping potential network calls. If you learned the contrary in an intro class, it may have just been something that the professor presented as a rule to simplify the concept of functions.


Lilixer

Thank you for sharing that I had no idea, I'm looking forward to the freedom I'll have writing functions from now on


Quplet

>I was taught to only ever have a single return statement in your functions. That is... Very stupid. Disregard this teaching, I've never seen this done.


Lilixer

Can do! Haha I see the faults of my teachings now


pink_arcana

Godot fragment shaders don't allow early returns, and it's totally cramping my style, haha. (I'm sure there's a good reason for it, but in an era of uniform constants, it feels a bit limiting.)


Zestyclose_Leg2227

As I understand, the single return comes from languages with manual memory allocation. You start a function in C, for example, and you declare some variables with "new", and then you can't return before calling your "delete" at the end of the function, or you will create a memory leak. In languages with a garbage collector  you are fine with several returns, as long as you use them to make your code easier to read (like this example) and not just randomly threw around into a nested hell of loops and ifs. :)


Lilixer

That explains a lot, I believe this was C! Wow I can't believe I have been applying that logic for years without really understanding why it was necessary and just using it by default, gotta love learning new things


Epsilia

If anyone is curious, this is also called a guard clause (or using multiple guard clauses). It's a very nice way to make code readable.


Shartun

is this still a thing on 4k monitors? I rarely hit horizontal width but almost always hit vertical height with my code. Unless you use your monitor in portrait mode, which I don't


Etzix

Most people still work a bit zoomed in on 4K monitors. I would also argue that you shouldn't need a specific monitor for readability. I have a colleague that argued we shouldn't have limits on line length because he uses an ultrawide monitor so everything fits on one line for him. Also there's nothing wrong with hitting vertical height, I think 80% of the files in our production environment requires you to scroll.


SkedaddlingSkeletton

> everything fits on one line for him. Make them try reading texts going for very long lines. After 3 or 4 lines it should start being hard to come back to the right one.


TPMR01

Am I the only one who, when I have to, does the former cuz I like it and feel it's more readable? + In those specific cases where you have multiple *singular* ifs nested, you can just combine the condition with and in a single if, which is my preferred approach in general


yellow-hammer

I just don’t get never nesters. The nesting makes perfect sense to me. Also seems more efficient, as all the equalities inside the nest never need to get computed if the first one is false. I mean it’s likely a minor thing in most cases but it’s there.


Etzix

Nesting a few times is fine. For me it's an issue if you have to scroll horizontally or have to cut lines in weird ways in order to avoid it. The efficiency argument is probably completely irrelevant since the compiler is probably cutting away all the garbage anyways.


S48GS

You can have logic of "connections" in script of "doorway" and "spawner" - basic OOP patterns - have logic related to current object in the object. Every object in Godot can have own script. This way you shown - is creating spaghetti logic - because you will have pieces of logic related to something somewhere else split in parts.


marco_has_cookies

Yeah it's spaghetti, if this is related to a game manager singleton, those objects should connect themselves. Btw when developing a game, spaghetti 🍝 is somehow accepted hahaha just don't put meatballs, just tomato sauce. also OP should learn of tree/graph visiting.


AndTer99

Unrelated, what is EventBus supposed to?


Alzzary

It's a code pattern that allows to send signals anywhere. Basically you have an autoload (EventBus) and you define signals inside. Then you can emit signals from anywhere, and all nodes that connected to the event bus with code will receive it.


siddharthagarwal440

So it's basically signalmanager?


Alzzary

if you want, yes. But it's not made to manage every single signals, it's to send data from one place to another if there's no obvious way to make it happen. Typically, it's great for UI because some things may happen in game that both your UI should reflect but also your game mechanics. Say for instance that the number of enemies you killed increases your score but it also triggers more difficult enemies to spawn. In your event but autoload, you can define signal enemy_died and when your enemy dies, you have this : EventBus.enemy_died.emit() all you need to do in your UI is to add the following at the ready function for instance : EventsBus.enemy_died.connect(count_dead_enemies) and define the function like this : func count_dead_enemies() -> void: enemy_killed_count += 1 #enemy_killed_count is an int variable that stores this information Event better, you can send data, as most beginners don't know it, but signals can send data as well, like signal enemy_died(enemy_score:int) when you emit this signal, you can pass an int as a parameter, and the connected function will receive it's value, like this : EventBus.enemy_died.emit(enemy_score_value) and the func in your UI can be like this : func count_dead_enemies(score:int) -> void: enemy_killed_score += score


siddharthagarwal440

Yeah do these things but I am used to calling it a signalmanager. I am learning to code through Godot so I am familiar with mostly the tutorials I have watched and they called the autoload a signalmanager.


Alzzary

The pattern's name is usually referred as an Event Bus in the godot community, hope this helps!


siddharthagarwal440

It does. Thanks


siddharthagarwal440

It does. Thanks


zer0xol

Cant the children make their own connections


Dookie_Loops_Bedroom

That's what I ended up doing.


dogsonbobnut

The yanderedev classic


Dizzy_Caterpillar777

This is nowhere near yanderedev coding style. OP's code is a bit longwinded but not stupid. Yanderedev style would be writing a separate `if node1.is_in_group("...")` for every hardcoded node.


dogsonbobnut

I would say 'eh close enough ' but you're not wrong, at least OP is intelligent


octod

Are those nodes added at runtime? If not, I would simply add a script to those and then call the eventbus stuff in the ready method.


TPMR01

Godot has aome functions that do a lot of work for you if you know how to use them. But if you ever have a case where you have to do something complex and it has no dedicated function then make a custom function and use it to make the code less clustered and obtuse.


Snailtan

Not sure what you are doing, but my approach would be that instead of searching for spawn nodes, you register spawn nodes in an array when they get put into the scene. That was if you are looking for them you can just accsess the array instead This goes for anything that needs to be searched. Have it register itself to a global array or list or whatever, so when you need them you can access this instead of searching. In small projects it's practically irrelevant but searching for node is if I remember right pretty costly


BackBufferCopy

get_children(true)?


ValianFan

I would either iterate the nodes through groups or I would create an array for it and do it through for node in nodes:


SensitiveBitAn

Omg thats spaghetti code!!!