https://docs.godotengine.org/en/3.1/getting_started/workflow/best_practices/scene_organization.html

This page in the docs really confuses me. It says multiple times that there should be NO dependencies between scenes

If at all possible, one should design scenes to have no dependencies. That is, one should create scenes that keep everything they need within themselves.

Warning. One should favor keeping data in-house (internal to a scene) though as placing a dependency on an external context, even a loosely coupled one, still means that the node will expect something in its environment to be true. The project’s design philosophies should prevent this from happening.

How is it possible to make scenes that interact at all then? For example, a fireball shot from a player colliding with a tree and setting it on fire

I assume the player, fireball, and tree would all be separate scenes, but how can they interact without creating dependencies?

To be honest, some of the Godot best practices confuse me, and I've worked with Godot for several years.

I think what the documentation is trying to express is that scenes should function without dependencies. For example, if you have a player script, it shouldn't require that there is a power-up object or a certain enemy in every level.

I use the export keyword to expose NodePaths to objects if a scenes has optional dependencies, where the code checks if the NodePath is set. Then I have the code only perform code that relies on dependencies if there is one setup. There are probably other ways to handle it, that is how I've done it.

So, using your example, you would have something like export (PackedScene) var fireball_scene = null in your Player and something like if (fireball_scene != null) in the code that spawns the projectile so that the Player is not dependent on the Fireball scene to function. Granted, the player will not be able to shot fireballs without it properly setup, leading to a lack of functionality, but it does not require the fireball scene.

For the tree and fireball, you can use signals, the has_method function, and other methods to determine the class/functionality necessary when they collide. For example, on the fireball you could have something like this (untested, minimal example):

extends Area2D
func _ready():
	connect("body_enter", self, "_on_body_entered_fireball")
func _on_body_entered_fireball(other):
	if (other.has_method("_catch_on_fire") == true):
		other.catch_on_fire()
	queue_free()

And for the tree:

extends StaticBody2D
func _catch_on_fire():
	print ("Tree destroyed because of fire")
	queue_free()

Hopefully this helps explain. I would not worry too much about it, especially if you are starting out. For small projects, cross-scene dependency is not too much of an issue, and it is generally more important to be learning, creating, and having fun. Cross-scene dependency issues are more troubling when working on larger projects, especially if you are working with multiple people on the same project. (Side note: Welcome to the forums!)

3 years later