I need help in loading scenes within Godot 3.5

Godot Version

Godot 3.5

Question
I have an issue within my game that is actually nearing completion.
Within the editor I am doing some scene instancing where when I have both a character selection screen and a level selection screen and after selecting the appropriate elements they get loaded into one master level scene, and the game works perfectly within the editor l, but as soon as I export for desktop or Android when I start from the main menu and click all the necessary elements of character and level, they don’t show up within the master scene as they do within the editor, i tried changing the naming to snake_case but it even made it worse within the editor now scenes don’t transition to the master they just transition back. What do I do???
It’s so annoying because I am so close to finishing the game.

Without seeing your code, I would guess that something is loading faster in-editor than it is once exported. What method are you using to load the scenes? Some are more robust than others (though more complicated) but they allow you to check whether something has loaded before you try to do something with it.

extends Node

onready var control = $TabContainer/Cars/RichTextLabel/control
onready var scroll_bar = $TabContainer/Cars/HScrollBar
#$Node/Control/TabContainer/Cars/HScrollBar.position.x = -$Control/TabContainer/Cars/HScrollBar.value

export(int) var speed: int = 7
export(float) var rotation_speed: float = 0.1
var direction = Vector2(-1, 0)
onready var parallax = $ParallaxBackground

func _process(delta):
control.position.x = -scroll_bar.value
parallax.scroll_offset += direction * speed * delta

var characters = [
preload(“res://car_scenes/mango_tango.tscn”), #0
preload(“res://car_scenes/beach_car.tscn”), #1
preload(“res://car_scenes/bike.tscn”), #2
preload(“res://car_scenes/the_hot_rod.tscn”), #3
preload(“res://car_scenes/jungle_jammer_final.tscn”), #4
preload(“res://car_scenes/african_car.tscn”), #5
preload(“res://car_scenes/monster_truck.tscn”) #6
]

func _on_Back_pressed():
SceneTransition.change_scene(“res://Scenes/main.tscn”)

func _on_Next_pressed():
SceneTransition.change_scene(“res://Scenes/level_test.tscn”)

self.queue_free()

func _on_MangoTango_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[0]

func _on_JungleJammer_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[4]

func _on_BeachBugger_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[1]

func _on_KaDukaSpeed_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[5]

func _on_MonsterTruck_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[6]

func _on_TheHotRod_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[3]

func _on_DirtMaster3000_pressed():
if (Characterselectionmanager.player == null):
Characterselectionmanager.player = characters[2]

This is the store scene, the second scene after the main menu start button is pressed.

The cars are all preloaded in an array and then when their individual buttons are clicked, the particular car is loaded into the var player variable (which is an autoload)

This is the player autoload script
extends Node

var player

Then this store scene has a button which when pressed transitions to the level selection screen, this is the script.

extends Control

export(int) var speed: int = 7
export(float) var rotation_speed: float = 0.1
var direction = Vector2(-1, 0)
onready var parallax = $ParallaxBackground

func _process(delta):
parallax.scroll_offset += direction * speed * delta
$control1.position.x = -$HScrollBar.value

func _ready():
for i in $control1/control.get_children():
i.text = i.name
for i in range($control1/control.get_child_count()):
Global.levels.append(i+1)
for level in $control1/control.get_children():
if str2var(level.name) in range(Global.unlockedlevels+1):
level.disabled = false
level.connect(‘pressed’, self, ‘change_level’, [level.name])
else:
level.disabled = true

#func change_level(lvl_no):

SceneTransition.change_scene(“res://Levels/Levels/level”+ lvl_no +“.tscn”)

#func _on_Button_pressed():

SceneTransition.change_scene(“res://Scenes/Main.tscn”)

var levels = [
preload(“res://Levels/Levels/level_1.tscn”),
preload(“res://Levels/Levels/level_2.tscn”),
preload(“res://Levels/Levels/level_3.tscn”),
preload(“res://Levels/Levels/level_4.tscn”),
preload(“res://Levels/Levels/level_5.tscn”),
preload(“res://Levels/Levels/level_6.tscn”),
preload(“res://Levels/Levels/level_7.tscn”),
preload(“res://Levels/Levels/level_8.tscn”),
preload(“res://Levels/Levels/level_9.tscn”),
preload(“res://Levels/Levels/level_10.tscn”),
preload(“res://Levels/Levels/level_11.tscn”),
preload(“res://Levels/Levels/level_12.tscn”),
preload(“res://Levels/Levels/level_13.tscn”),
preload(“res://Levels/Levels/level_14.tscn”),
preload(“res://Levels/Levels/level_15.tscn”),
preload(“res://Levels/Levels/level_16.tscn”),
preload(“res://Levels/Levels/level_17.tscn”)
]

func _on_1_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[0]

func _on_2_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[1]

func _on_3_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[2]

func _on_4_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[3]

func _on_5_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[4]

func _on_6_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[5]

func _on_7_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[6]

func _on_8_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[7]

func _on_9_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[8]

func _on_10_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[9]

func _on_11_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[10]

func _on_12_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[11]

func _on_13_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[12]

func _on_14_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[13]

func _on_15_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[14]

func _on_16_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[15]

func _on_17_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[16]

func _on_18_pressed():
if (Levelselectionmanager.level == null):
Levelselectionmanager.level = levels[17]

func _on_Start_pressed():
SceneTransition.change_scene(“res://Scenes/Level.tscn”)

Same logic as the player selection script, levels preloaded within an array, level button is clicked its loaded into an autoload levelselection manager script like this

extends Node

var level

Then again within this scene, there is a button that loads a master level scene where all the button clicked resources ie the car selection and level selection load into using instanciation and call_deferred()

This is the script below;

onready var givenPlayer = Characterselectionmanager.player.instance()
onready var givenLevel = Levelselectionmanager.level.instance()

func _ready():
spawn_level()
spawn_characters()

func spawn_level():
call_deferred(“add_child”, givenLevel)

func spawn_characters():
call_deferred(“add_child”, givenPlayer)

Within the editor when i finally load the master scene, it properly instances the correct car and level but when i export, all the appropriate buttons are clicked but once i transition to the level scene, nothing shows but the default empty window.
i thought it was an issue of naming but i changed to snake_case just like it recommends in the documentation but it never worked. Is the issue preloading, loading, code compilation, i ticked to export all resources within the project but to no avail

Your help is very much appreciated!!!

I realize you’re nearing the end of your project, but you might want to look into ResourceLoader

I have a hunch you might be attempting to access something before it’s done loading. Resources tend to load almost instantly locally but then once they’re “out in the wild” it takes more time to load them into your project, which can expose logic that only works locally. Again, just a guess… I made a video on a more robust way to load scenes which you can watch here if you’d like. Bear in mind, it’s written for Godot 4, but the concepts are the same even if the code can’t be copy/pasted into your project.

1 Like

Thank you so much for this but in Godot 3.5 ResourceLoader and all of it’s functions are not present, it’s only in Godot 4 where things like load threaded get status and the like are available, do you know of any other way? Thank you again.

Are you sure? I know they changed ResourceLoader in 4.0, but I thought there was a version of it in 3.5. The link I sent is to the 3.5 documentation (at least that’s what it says at the top of the page… maybe the page is busted?)

1 Like

oh yes i have seen, so how do you recommend i use it because i have used ResourceLoader.load() on all the character and level scenes but instead when i export and transition to change from the store scene, it just plays the transition and then goes back to the store scene (not going to the level scene as it does within the editor)
Is there another way you know of, my ears are open. Thank you.

Would you be willing to share your project files (either GitHub or zip, whatever is easier)? I’d be happy to take a peek this weekend to see if I can figure out why it’s failing on you. If not no worries.

Strangely (or maybe not so much these days :rofl:) this video just popped up in my YouTube feed. It shows how to use ResourceLoader in 3.5

My current blind hunch is that your logic is working locally because what you’re loading loads instantly when testing. But in production it’s a little slower and so you might be trying to act on a level (or whatever you’re loading) before it’s done loading. So if I were debugging this, I would try to verify that. If so, the ResourceLoader can be used to make sure that you’re never getting ahead of your loading progress (as shown in the video above).

Again, this is just the first place I would investigate if I were in your shoes. If you want to pull that thread in the meantime, might not be a bad place to start. Otherwise, I can have a look over the weekend if you don’t beat me to a solution.

Ok here is the repo, I’m a bit of a newbie so there’s a lot of disorganization :sweat_smile:

Ooops, forgot this was a Godot 3.5 project :stuck_out_tongue: Might take a little while longer because I don’t have that installed anymore AND I’ll need to remind myself of what has changed between the two versions. :thinking:

1 Like

OK, I got it working. I’m not sure it’s the best solution but given that you’re at the end of the project… this should get you across the finish line.

The problem was as I’d guessed. You’re going a lot of loading that happens instantly on desktop, but not once it’s exported. So the massive amount of preloads at the beginning of Store.gd are hanging the project.

var characters = [
	preload("res://Levels/Mango Tango.tscn"), #0
	preload("res://Levels/Beach car/beach car.tscn"), #1
	preload("res://Levels/Dirt Master/bike.tscn"), #2
	preload("res://Levels/The Hot Rod.tscn"), #3
	preload("res://Levels/Jungle jammer Final.tscn"), #4
	preload("res://Assets/African Car.tscn"), #5
	preload("res://Levels/Monster Truck/monster truck.tscn")] #6

I got rid of that array entirely, you don’t need it. Then I’m just loading those directly when clicked - you don’t need preload them all if the user is only ever going to use one vehicle.

func _on_MangoTango_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Levels/Mango Tango.tscn")
	
func _on_JungleJammer_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Levels/Jungle jammer Final.tscn")
	
func _on_BeachBugger_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Levels/Beach car/beach car.tscn")
	
func _on_KaDukaSpeed_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Assets/African Car.tscn")
	
func _on_MonsterTruck_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Levels/Monster Truck/monster truck.tscn")
	
func _on_TheHotRod_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Levels/The Hot Rod.tscn")
	
func _on_DirtMaster3000_pressed():
	if (Characterselectionmanager.player == null):
		Characterselectionmanager.player = load("res://Levels/Dirt Master/bike.tscn")

If you want to keep that array, fill it with the path to your resources rather than preloading all of them at once when that array is started. Then just pass the string into the load (not preload) function inside of the _pressed handlers.

Here’s the docs on load. I tend not to use this method because it will “hang” your project while attempting to load (this is why the docs suggest ResourceLoader at the bottom of this block… however if what you’re loading isn’t massive you can get away with the simplified load() call. Being that you’re at the end of your project, I’d keep it simple until you discover you have to use ResourceLoader to read the loading progress and display that to the user - you may not have to do that.

Resource load(path: String)

Loads a resource from the filesystem located at path. The resource is loaded on the method call (unless it’s referenced already elsewhere, e.g. in another script or in the scene), which might cause slight delay, especially when loading scenes. To avoid unnecessary delays when loading something multiple times, either store the resource in a variable or use preload().

Note: Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing “Copy Path” or by dragging the file from the FileSystem dock into the script.

Load a scene called main located in the root of the project directory and cache it in a variable.

var main = load(“res://main.tscn”) # main will contain a PackedScene resource.

Important: The path must be absolute, a local path will just return null.

This method is a simplified version of ResourceLoader.load(), which can be used for more advanced scenarios.

But yeah, I think your project was hanging on all those preloads running at once and waiting for the animation to finish wasn’t sufficient… so you were indeed trying to access stuff before it existed as suspected.

I also noticed you have some other errors in your project which may seem unrelated, but should be cleaned up before you finish this. I hope this gets you unstuck. You can take it from here :slight_smile: Good luck with the rest of your project!

1 Like

Well thank you sooo much but I had already tried this method but it still never worked. Although it has improved the loading time, could this be a PC hardware issue or ?? Could it be that the plugins in use are not compatible with the export specifications or maybe the Godot version itself.

This is the screen I get instead of the car and level when exported

Something must be different, because what I sent you does work. I ran several tests and confirmed it. I’m not home but I can try to zip up a fixed version and return it to you. I didn’t because the game is enormous on my screen (is this a mobile game?) and so I could see a lot of the UI without moving some things around.

I’m not using preload anywhere. Were you careful to make that change inside you click handlers?

In fairness, I was exporting to a Mac build, not PC so maybe that’s the variable here? I was able to reproduce the problem you described before fixing it though, so I don’t think that’s the issue.

oh yes it is a mobile game, maybe its because of the PC build, do you think the issue is with the export template? or maybe the plugins used within the project maybe the .zip will be different.

well (and this is going to make you roll on the floor laughing) i never ticked the box to export all resources within the project, this is so funny because i spent weeks on this issue. But anyways i have learnt so much from you these past few days and im so thankful

Anyways what would you recommend that i fix within the game? Appreciate the help

Oh I was just referring to the errors in the debug console. I’m glad you got it working. We all go through these facepalm moments. Don’t sweat it :stuck_out_tongue_closed_eyes: