Scene Communication

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Clifford

Hello !

I’m still studying on scene tree design and ways to pass information from one scene’s child node to another.

I have made my own first design and would like to get insights from others on it in order to get better understanding/mindset.

What I have so far:
Imgur


An example of one feature in the current game:

Inside the Player scene:
The root node has assigned signals for its children to use, one of which is the player_aimed signal. This signal is emitted when the player pressed the aim button.
signal player_aimed(player_sprite_node)

Inside the Test scene:
Using the Godot UI, I connected the player_aimed signal to both the CameraRig and the Gun scenes root node ( _on_Player_player_aimed(player_sprite_node) )

Inside the Gun scene:
The root node receive the signal and uses a setter to flip its _process function on. The _process function sole purpose is to rotate the Gun root node to mouse position by using the passed player_sprite_node information.

Inside the CameraRig scene:
The root node receive the signal and uses a setter to flip its _process function on. The process function sole purpose is to pass the get_camera_screen_center information to the Gun scene by emitting a signal called camera_moved to the Gun scene.
signal camera_moved(camera_global_center)

Inside the Test scene:
Again, I use the engine UI to connect the camera_moved signal from the CameraRig scene to the Gun scene to pass the get_camera_screen_center information.

Inside the Gun scene:
func _on_CameraRig_camera_moved(camera) → void:
do maths stuff that keeps raycast length within viewport

This is because in my game I don’t want the player to be able to shot at things outside the camera view

All in all I’d say there is a lot of signals being emitted back and forth, I have been debating on whether I should make the Test node responsible in connecting its children signals or to keep all the signals in a singleton, but in the end I’m unsure of which to method to use or what direction I should take. I am afraid that with my current design, the game code would grow to become difficult for me to navigate or maintain.


I hope the above is clear, I’d gladly clarify otherwise.
I’d appreciate any comment and feedback on this.

Thank you in advanced for your time and help.

:bust_in_silhouette: Reply From: klaas

Hi,
this is more of a phylosophical question. Its monolythic vs modular.

While modular programming is more over engineered, its usualy better to understand/edit later in the developing process. Monolythic structures are more likley to be performant, but due to its spaghetti-code-tendency often its hard to refactor or even to understand its workings later.

How i programm:
i allways have a “app” singleton … this is the center object to register every important game object. So when a bullet want to interact with the player it can get the player via app.player … this makes finding/connecting objects way easier. Also the app manages the primary app stages like menu, ingame menu, level loading etc or holds an instance to a designated object for handling this.

I try to design all objects as self-organising as possible. The final goal is, that when i remove/replace a gameobject the game still runs without fiddiling around in other places. Even if this is the overall design idea behind object-oriented programming its often hard to archive true independence.

If objects are closely rely on each other, i try to group them in scenes (to include) that are independent from everything else. So a player will be in a player scene. The level in a level scene. The UI in a ui scene. So everything should be interchangeable.

Because signals are global events i try to design them as logical and independent as possible. There should be no “extra for this other object” signal.

I programm everything the “nice-way-first” (i made up this myself). I write a dummy code like i think it would be the nicest way to have it, easy and convinient. Then i try to design everything around this nice structure to make it work. This results in convenience methods and structures that are actually “nice” to use later in the development process.

All in all for me i think its best to programm every compound of the game like a plugin. Independent with logical connectors and signals and convinient usage.

Thank you very much for sharing!
I really like how you program, its really neat.

Its my first time seeing this “app” singleton pattern you have, how would you reference game objects in the current level scene? I am confused because the path would differ from one level to the next right? Or with this pattern you have to keep the level scene tree structure similar for all levels?

Clifford | 2021-09-21 11:55

Hi
I usually avoid any path related accesss. In most cases i find it unreliable and unflexible.

i would try to let most of the game object manage themself … a bullet gets spawned with a position and motion vector then it travels and hits, deals damage or just decay after a while, deleting itself.
For any other objects like enemies i would use the group feature of godot. For the player i would register the player on _ready to the app singleton for easy access. For complex special object relations i would write a manager-script wich can be easyly included in any level.
So, i would write any script so that the level scene structure is irrelevant.

klaas | 2021-09-21 14:51