Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add arguments to get_tree().change_scene_to_*() #10293

Open
Germenzi opened this issue Jul 27, 2024 · 3 comments
Open

Add arguments to get_tree().change_scene_to_*() #10293

Germenzi opened this issue Jul 27, 2024 · 3 comments

Comments

@Germenzi
Copy link

Germenzi commented Jul 27, 2024

Describe the project you are working on

Multiplayer project where TCP should be used, so High-level multiplayer API isn't my choice.

Describe the problem or limitation you are having in your project

The problem is in switching between several scenes saving connection StreamPeerTCP instance. Some kind of autoload help to solve this problem, but this solution have some issues:

  • When one project is used both for server and client, autoloads cause confusion as to what writing another piece of code because you have to think about what the part of the project this code belongs to and make sure that you don't use wrong autoload.
  • In autoload's script you can't use scene unique nodes and generally alter current scene, because it isn't guaranteed that you in expected scene, so you need to write extra code to track the current scene or use signals etc. Using scene directly from autoload is complex (if i have 10 scenes?) and hard to debug, while using some kind of proxy doesn't guarantee that another event will be processed or some events may be lost while scene changing.
  • Using autoload you have to disconnect from server manually. Also after disconencting corresponding autoload remains in the tree (so there is no some kind of RAII)

And as for me, I need more than one connection and/or server (chat server/client, matchmaker, room server etc.) in one process. In my test project I wrote TCPNetworker manager (which is autoload and keeps all those problems), but it still doesn't fit me and that's off-topic. (Code is so messy, you know)

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I propose to add parameter(s) to get_tree().change_scene_to_* which could be accepted via get_tree().get_scene_argument,
simple concept like cmdline arguments.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Example of changing scene when button pressed:

func _on_button_pressed():
    # here 100 - player hp for example, while 7635 is player score
    get_tree().change_scene_to_file("res://level-2.tscn", 100, 7635)

And in level-2 scene those arguments can be accepted as below:

# any node in scene (or in a tree) after changing scene
func _enter_tree():
    print(get_tree().get_scene_argument(0)) # prints player hp in scene 'initialization'

If this enhancement will not be used often, can it be worked around with a few lines of script?

Yes, it can be done using custom SceneTree like below:

extends SceneTree

class_name MySceneTree

var _params : Dictionary = {}
var _new_scene_with_params : bool = false


func _initialize() -> void:
	node_added.connect(_on_node_added)


func change_scene_to_file_parameterized(file:String, parameters:Dictionary={}) -> Error:
	_new_scene_with_params = true
	_params = parameters
	return change_scene_to_file(file)


func get_scene_parameters() -> Dictionary:
	return _params


func _on_node_added(node:Node) -> void:
	if node == current_scene:
		current_scene.tree_exited.connect(_on_scene_deleted)


func _on_scene_deleted() -> void:
        # if we uses default change_scene_to_* one think there is no arguments, so it should be automatically cleared
	if not _new_scene_with_params:
		_params = {}
	else:
		_new_scene_with_params = false

Is there a reason why this should be core and not an add-on in the asset library?

Generally - no. But being core feature it will be a lot more readable and reliable. Also custom SceneTree doen't support code autocompletion. Another reason is that scene files may contain 'neccesary' arguments which will be checked if this scene used in change_scene_to_*. And this will avoid using autoloads just to throw data to the next scene, removing unnecessary in other scenes nodes.

@AThousandShips
Copy link
Member

Essentially the same as:

But with specific case where it would be used

@Germenzi
Copy link
Author

Essentially the same as:

But with specific case where it would be used

Not exactly, I think. Passing parameters to PackedScene still doesn't allow you to pass parameters into get_tree().change_scene_to_*, because you don't call PackedScene.instantiate directly.

@AThousandShips
Copy link
Member

AThousandShips commented Jul 28, 2024

It would be part of achieving it easily, by just passing those arguments when calling the instantiate

However the workaround is trivial enough that I don't see this being necessary, it isn't something that's hard to do in your project with your own specific needs, and with your specific setup you're probably better off with a custom solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants