Im working on a 3D platforming game and i want it so when the player touches the flag it switches to another scene. Any suggestions?

  • There are multiple ways to do it, but a good method would be to use signals and a function that frees the current scene.

    If you have a collision for your flag (like an Area2D or something) you should be able to see its available signals in the "Node" tab on the right when the node is selected in the scene tree (or look up Area2D for the signal descriptions in the manual and find the one that matches best with your collision system).

    You can unload the scene that you want to replace in this function (and it depends on how your game is designed). Let's assume you want to free your scene, named "Level1" which is attached to the root node (aka., it is the top-most node in your game) you might do something like this for your signal function:

    # Queue the current scene to free on the next frame:
    var root_node = get_tree().get_root()
    var scene_node = root_node.get_node("Level1")
    scene_node.queue_free()
    
    # Load in some scene from our project files:
    var new_scene_resource = load("res://Levels/Level2.tscn") # Load the new level from disk
    var new_scene_node = new_scene_resource.instantiate() # Create an actual node of it for the game to use
    root_node.add_child(new_scene_node) # Add to the tree so the level starts processing

    And done. Now, that said, the SceneTree also has built-in 'change scene' functions which I assume do just as I did above in one function. I generally don't use them because I usually have some 'global nodes' inbetween the root and my actual level scene, but if you don't then it should be simpler in that you can just call:

    get_tree().change_scene_to_file("res://Levels/Level2.tscn")

It depends on what game engine and programming language/framework you are using, as they each have their own syntax and way of doing things.

Generally, the most common way to transition between scenes is to load the target scene asynchronously and switch to it when it's finished loading. This is often done using event listeners. So, you could set up an event listener for a collision between the flag and the player, and then when that occurs, start loading the target scene asynchronously. When the loading process is finished, switch to the loaded target scene.

There are multiple ways to do it, but a good method would be to use signals and a function that frees the current scene.

If you have a collision for your flag (like an Area2D or something) you should be able to see its available signals in the "Node" tab on the right when the node is selected in the scene tree (or look up Area2D for the signal descriptions in the manual and find the one that matches best with your collision system).

You can unload the scene that you want to replace in this function (and it depends on how your game is designed). Let's assume you want to free your scene, named "Level1" which is attached to the root node (aka., it is the top-most node in your game) you might do something like this for your signal function:

# Queue the current scene to free on the next frame:
var root_node = get_tree().get_root()
var scene_node = root_node.get_node("Level1")
scene_node.queue_free()

# Load in some scene from our project files:
var new_scene_resource = load("res://Levels/Level2.tscn") # Load the new level from disk
var new_scene_node = new_scene_resource.instantiate() # Create an actual node of it for the game to use
root_node.add_child(new_scene_node) # Add to the tree so the level starts processing

And done. Now, that said, the SceneTree also has built-in 'change scene' functions which I assume do just as I did above in one function. I generally don't use them because I usually have some 'global nodes' inbetween the root and my actual level scene, but if you don't then it should be simpler in that you can just call:

get_tree().change_scene_to_file("res://Levels/Level2.tscn")

    boy that post above me is a classic example of overengineering a solution. I'm certain you have reasons for doing it that way but the average developer working on their first couple games is gonna look at that and get a headache!

    the simple, easy way to do this that you're probably looking for is: add an area3D to your flag, and use the "on_body_entered" signal. check to see if it's the player somehow (probably through body.is_in_group() or body.name) and then if it is, use get_tree().change_scene("name of your scene")

      samuraidan

      boy that post above me is a classic example of overengineering a solution. I'm certain you have reasons for doing it that way but the average developer working on their first couple games is gonna look at that and get a headache!

      the simple, easy way to do this that you're probably looking for is: add an area3D to your flag, and use the "on_body_entered" signal. check to see if it's the player somehow (probably through body.is_in_group() or body.name) and then if it is, use get_tree().change_scene("name of your scene")

      Is that not exactly what I said? Area2D, signal a function that executes get_tree().change_scene_to_file("res://Levels/Level2.tscn").

      I did not see change_scene in the manual for SceneTree in Godot 4 so I did not suggest it. I am assuming it was replaced but feel free to correct me on that one.

      My longer answer was specifically for loading in a scene if you aren't replacing your root scene, and I stated as much as well as an answer for if it was (which is what your example addresses as well). I don't know how the original poster has his/her game laid out. If you have a better solution for the first case, I'm all ears.

        Binsk you're right about they changed it to change_scene_to_file() but I maintain that answering a question that wasn't asked (they asked how to change the scene and that's it, not how to change the scene without replacing a root scene) needlessly complicated things unless you clearly mark it as doing something extra and separate it from the shortest and simplest possible answer. I can't count the amount of hours I've had to trawl through someone's overengineered answer to a simple question only to find out I could do what I wanted with one simple line and I'm trying to save anyone in the future from having to do the same thing.

        I firmly believe you think you're doing a good thing by adding all the extra steps, but if someone asks "how do I walk?" you start with "put one foot in front of the other", you don't start with a paragraph on how physics works.

        Frankly I'm inclined to argue for avoiding changing the whole scene whenever possible. It was probably a mistake to include the old .change_scene() as it was in the first place. It's likely to cause more problems than it resolves. Especially for new users who don't yet properly understand godots scene tree and what (packed) 'scenes' are and what they are not, and how it all works.

        Adding to what everyone above said, although you can call the change_scene_to_file and call it a day, how are you going to handle the transition?
        When your level is the root node:

        • Every level will handle the scene change.
        • Every level scene will have some of the same stuff, like GUI and player.
        • You need to use autoloads to transfer information between levels. (IDK if they're bad, but I tend to avoid them whenever possible as a beginner)
        • Whenever you need to add something non single level specific, you have to apply it to all your levels.
        • Your levels are overloaded (hah)!

        However with a root node:

        • The root node's responsibilities are to handle scene loading and unloading, hold the shared stuff, and trigger its children in some ordered fashion. The levels themselves are not concerned with that anymore.
        • Whenever you need to add something, no need to change the levels scene or code, levels will only emit some signal, and the root will listen to it and handle the rest.
        • Any other child of root can do the same, signal up. The root will handles everything by calling down its children.
        • Transition animation, for example, can be as easy as having a transition control child scene that plays when root is changing scenes, and fades out after a certain time or when the next level scene is ready.
        • Your MainMenu can be yet another level, but with some buttons, and the player disabled, or it can be a creative special level.
        • The same can go to the LevelsPicker scene.
        • As you can see, you can add more to your game, with minimal to no change in your levels.
          • Root starts playing the transition animation by simply calling transition.play(), transition scene should handle this.
          • Root takes data from the current level, maybe re-parent the player to itself, prepares the current level to be deleted.
          • Root disconnects some signals, unloads the current level scene.
          • Root loads the next level scene, connects the appropriate signals to itself and children, etc...
          • Level scene is ready, emits ready
          • Root listens to ready and tells the transition to fade out, transition handles that.
          • Player plays, reaches the goal, level emits the signal
          • Root listens to the level's signal, and repeats what happened before
          • Player wants to quit, so pauses and press the main menu button, GUI emits the signal and root changes the scene from level to main menu!
        • Every scene is only concerned with what it does, which means easier to understand code.
        • Levels scene will do what levels do, same for: main menu, levels picker, transition animation, the player, the gui, and then there is the glue (root node)
        • That was only an example
        • I hope someone posts some good rules of thumb, better implementations, simpler ways, etc...

        Its negative can be, that this might seem like over-engineering, over-complicating a simple thing, and this might be right, and you might really will not need that, but it is good to know about such solution. As it sure simplifies everything once you know how to set it up, know when and why to use it, and tweak it to your project's specific needs. Just like state machines. (I'd even argue that this is some specific way of doing a state machine)

        4 days later

        Lavamonke

        Man i thought this code would be easy 😫

        Welcome to the world of programming. 😛

        does this code work for 3D spaces?

        This code will work for any scene in your game; the type doesn't matter.