How'd the Orig Project Get Away With Using Cyclical References?

When I tried putting them in my own project, it broke. Yet the instructor’s, despite having the same stuff, works just fine even after being reloaded in Godot 4.2. I compared the code and level-setups of the two projects, but I’m still lost.

Can anyone explain to me how one can lead to things breaking while the other works fine? I took a look at this topic, and I’m still lost.

Which section/area/code/feature/etc. are you seeing this in? A hard example would help.

My best guess at the moment is that you’re seeing something regarding Kaan’s use of signals. I’ll wait to say anything else until I have a better idea of what you’re experiencing on your end.

It’s in the More Levels video where he has the level script use an exported next_level var like so:
@export var next_level: PackedScene = null

And he assigns the packed scene from the project to things like so:
image

On my end, that assignment alone breaks the project upon reloading it. Another weird difference is that on my end, when I assigned the scene file, it comes with some image:
image

Another thing to note is that when I assign a scene to next_level that isn’t a level, the project doesn’t break. Can you explain what you mean by a hard example, by the way?

Basically this. I had no idea what part of the course you were at =)

Kaan is not making cyclical references here, he is making a chain. Each level’s next_level field is filled with the one that comes after. I can only assume that’s what you’re doing too since you’re placing the level_2 scene as this level’s next_level value, but I can’t actually see from these screenshots if this is the inspector for level 1. Even if level 2’s next level was set to level 2 (itself), or level 1 (backwards), it wouldn’t constitute a cyclical reference because you’re only making one “hop” at once. Independent. What happened in the topic you referenced is that OP’s scenes were referencing each other in a way that ended up making an infinite loop of level hops, so hopefully that answers why Kaan is able to do what he does here.

Anyway, have you tried running level 2 from the start to ensure it works properly as a standalone level? The fact that you’re seeing a black image in place of what should be a thumbnail of the level makes me wonder if there’s a problem there. In relation to that,

you’re probably aware that PackedScene is just any scene and not necessarily a level, so this behaviour makes sense and further suggests there is something wrong specifically with level 2. I’d start looking there.

3 Likes

Nice post as i had to get a sanity check from Kaan to make sure i wasnt going mad myself lol.

Thanks again for being a wonderful part of our community :slight_smile:

1 Like

Cheers Marc ^v^

Understood about the cyclical references. I too was intending to make a chain.

Yes, I ran all 3 levels to make sure they worked fine standalone. It’s only when setting next_level to any of those that things went pear-shaped. And yes, I’m aware that PackedScene isn’t necessarily a level.

But as per your suggestions, I’ll examine the levels more closely to see if I messed anything up.

1 Like

Turns out it wasn’t chaining the levels through the level script that broke the project. It was assigning one of the levels to the Win Screen script as the thing to load when Level 3 is cleared. The difference between mine and Kaan’s is that his script loaded the title scene from file, while mine let you set the scene to load through the Inspector. I don’t see why my approach breaks things, though…

Ok. Everything in the previous post sounds good. Regarding this one, let’s see if I understand correctly.

To me, this sounds like level_3’s next_level is being set to win_screen.tscn instead of being left null, I’m guessing with the intention of using it as a theoretical final level instead of an overlay like what Kaan does. That can work, and it also eliminates the need for is_final_level. Similar to my project actually.

I downloaded the final commit of Martian Mike and tried this out to see if I could make it break, but it worked just fine. Changing the value of is_final_level didn’t make a meaningful difference either.

I made this change too by creating an @export variable in the win screen scene to hold the start menu, then using change_scene_to_packed(start_menu). Again, no issues. I don’t see anything wrong with your approach, and the good news here is that this test confirms that view.

Is there a specific error message you’re seeing, and either way, precisely how far do you get before things fall apart?

1 Like

No, I did not have win_screen assigned to level_3. It was level_1, level_2, or level_3 being assigned to win_screen’s @export variable that broke things. I managed to fix the issue by having win_screen.gd do the same thing Kaan’s did: load another scene through change_scene_to_file instead of change_scene_to_packed. This was all before I got to the lesson about the start menu.

Afterwards, though, I had start_menu assigned to win_screen, going back to using change_scene_to_packed. And… just like it did on your end, it worked as intended. I’m still not sure why my old approach broke things, but alright :man_shrugging:

As for the error message caused by the old approach, I didn’t get a specific one. Just a popup about how my levels have broken dependencies.

Glad you found a fix, well done!

Aha! This is what I needed to know. I reproduced the problem on my end, and it looks like after all of this discussion, I think you were in fact creating a circular reference after all.

After some extensive testing, I managed to make your original approach work. The problem was that if every scene involved in the control loop (level 1, level 2, level 3, win screen) has an @export PackedScene belonging to that set, the control loop breaks. Not 100% certain as to why, but it definitely has to do with the scene not being unloaded properly before code tries to load it again. I feel like it’s some sort of off-by-one bug in Godot’s scene-changing code itself, because inserting the start menu (which has no @export PackedScene loop member) into this loop magically made everything work. I can’t get closer than that to a full explanation I’m afraid; it’s a bit beyond what I know.

(It’s also worth noting I didn’t have a broken dependencies popup, so there may have been something additional in your project that I couldn’t reproduce).

I had lots and lots of problems with this when I was extending these projects after finishing the lessons, but they manifested differently for me than they did for you. Personally, I’ve found that loading scenes by filepath has been far more reliable than using @export variables to pass scenes into the inspector directly (probably because it breaks apart these control loops), so for any future projects, I’d highly recommend working around that technique. @exports can still be part of the solution though, if you want; a few ideas:

  • Ints and parsing
  • Dictionaries
  • Arrays
  • Enums

Congratulations again on fixing the issue, and good luck with the rest of the course =)

2 Likes

Thank you very much for the patience and feedback ^^ I’ll be sure to keep it in mind for future projects.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms