.. _doc_scene_organization: Scene organization ================== This article covers topics related to the effective organization of scene content. Which nodes should one use? Where should one place them? How should they interact? How to build relationships effectively -------------------------------------- When Godot users begin crafting their own scenes, they often run into the following problem: They create their first scene and fill it with content only to eventually end up saving branches of their scene into separate scenes as the nagging feeling that they should split things up starts to accumulate. However, they then notice that the hard references they were able to rely on before are no longer possible. Re-using the scene in multiple places creates issues because the node paths do not find their targets and signal connections established in the editor break. To fix these problems, one must instantiate the sub-scenes without them requiring details about their environment. One needs to be able to trust that the sub-scene will create itself without being picky about how one uses it. One of the biggest things to consider in OOP is maintaining focused, singular-purpose classes with `loose coupling `_ to other parts of the codebase. This keeps the size of objects small (for maintainability) and improves their reusability. These OOP best practices have *several* implications for best practices in scene structure and script usage. **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. If a scene must interact with an external context, experienced developers recommend the use of `Dependency Injection `_. This technique involves having a high-level API provide the dependencies of the low-level API. Why do this? Because classes which rely on their external environment can inadvertently trigger bugs and unexpected behavior. To do this, one must expose data and then rely on a parent context to initialize it: 1. Connect to a signal. Extremely safe, but should be used only to "respond" to behavior, not start it. Note that signal names are usually past-tense verbs like "entered", "skill_activated", or "item_collected". .. tabs:: .. code-tab:: gdscript GDScript # Parent $Child.connect("signal_name", object_with_method, "method_on_the_object") # Child emit_signal("signal_name") # Triggers parent-defined behavior. .. code-tab:: csharp // Parent GetNode("Child").Connect("SignalName", ObjectWithMethod, "MethodOnTheObject"); // Child EmitSignal("SignalName"); // Triggers parent-defined behavior. 2. Call a method. Used to start behavior. .. tabs:: .. code-tab:: gdscript GDScript # Parent $Child.method_name = "do" # Child, assuming it has String property 'method_name' and method 'do'. call(method_name) # Call parent-defined method (which child must own). .. code-tab:: csharp // Parent GetNode("Child").Set("MethodName", "Do"); // Child Call(MethodName); // Call parent-defined method (which child must own). 3. Initialize a :ref:`FuncRef ` property. Safer than a method as ownership of the method is unnecessary. Used to start behavior. .. tabs:: .. code-tab:: gdscript GDScript # Parent $Child.func_property = funcref(object_with_method, "method_on_the_object") # Child func_property.call_func() # Call parent-defined method (can come from anywhere). .. code-tab:: csharp // Parent GetNode("Child").Set("FuncProperty", GD.FuncRef(ObjectWithMethod, "MethodOnTheObject")); // Child FuncProperty.CallFunc(); // Call parent-defined method (can come from anywhere). 4. Initialize a Node or other Object reference. .. tabs:: .. code-tab:: gdscript GDScript # Parent $Child.target = self # Child print(target) # Use parent-defined node. .. code-tab:: csharp // Parent GetNode("Child").Set("Target", this); // Child GD.Print(Target); // Use parent-defined node. 5. Initialize a NodePath. .. tabs:: .. code-tab:: gdscript GDScript # Parent $Child.target_path = ".." # Child get_node(target_path) # Use parent-defined NodePath. .. code-tab:: csharp // Parent GetNode("Child").Set("TargetPath", NodePath("..")); // Child GetNode(TargetPath); // Use parent-defined NodePath. These options hide the points of access from the child node. This in turn keeps the child **loosely coupled** to its environment. One can reuse it in another context without any extra changes to its API. .. note:: Although the examples above illustrate parent-child relationships, the same principles apply towards all object relations. Nodes which are siblings should only be aware of their hierarchies while an ancestor mediates their communications and references. .. tabs:: .. code-tab:: gdscript GDScript # Parent $Left.target = $Right.get_node("Receiver") # Left var target: Node func execute(): # Do something with 'target'. # Right func _init(): var receiver = Receiver.new() add_child(receiver) .. code-tab:: csharp // Parent GetNode("Left").Target = GetNode("Right/Receiver"); public class Left : Node { public Node Target = null; public void Execute() { // Do something with 'Target'. } } public class Right : Node { public Node Receiver = null; public Right() { Receiver = ResourceLoader.Load