scene_organization.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. .. _doc_scene_organization:
  2. Scene organization
  3. ==================
  4. This article covers topics related to the effective organization of
  5. scene content. Which nodes should you use? Where should you place them?
  6. How should they interact?
  7. How to build relationships effectively
  8. --------------------------------------
  9. When Godot users begin crafting their own scenes, they often run into the
  10. following problem:
  11. They create their first scene and fill it with content only to eventually end
  12. up saving branches of their scene into separate scenes as the nagging feeling
  13. that they should split things up starts to accumulate. However, they then
  14. notice that the hard references they were able to rely on before are no longer
  15. possible. Re-using the scene in multiple places creates issues because the
  16. node paths do not find their targets and signal connections established in the
  17. editor break.
  18. To fix these problems, you must instantiate the sub-scenes without them
  19. requiring details about their environment. You need to be able to trust
  20. that the sub-scene will create itself without being picky about how it's used.
  21. One of the biggest things to consider in OOP is maintaining
  22. focused, singular-purpose classes with
  23. `loose coupling <https://en.wikipedia.org/wiki/Loose_coupling>`_
  24. to other parts of the codebase. This keeps the size of objects small (for
  25. maintainability) and improves their reusability.
  26. These OOP best practices have *several* implications for best practices
  27. in scene structure and script usage.
  28. **If at all possible, you should design scenes to have no dependencies.**
  29. That is, you should create scenes that keep everything they need within
  30. themselves.
  31. If a scene must interact with an external context, experienced developers
  32. recommend the use of
  33. `Dependency Injection <https://en.wikipedia.org/wiki/Dependency_injection>`_.
  34. This technique involves having a high-level API provide the dependencies of the
  35. low-level API. Why do this? Because classes which rely on their external
  36. environment can inadvertently trigger bugs and unexpected behavior.
  37. To do this, you must expose data and then rely on a parent context to
  38. initialize it:
  39. 1. Connect to a signal. Extremely safe, but should be used only to "respond" to
  40. behavior, not start it. By convention, signal names are usually past-tense verbs
  41. like "entered", "skill_activated", or "item_collected".
  42. .. tabs::
  43. .. code-tab:: gdscript GDScript
  44. # Parent
  45. $Child.signal_name.connect(method_on_the_object)
  46. # Child
  47. signal_name.emit() # Triggers parent-defined behavior.
  48. .. code-tab:: csharp
  49. // Parent
  50. GetNode("Child").Connect("SignalName", Callable.From(ObjectWithMethod.MethodOnTheObject));
  51. // Child
  52. EmitSignal("SignalName"); // Triggers parent-defined behavior.
  53. .. code-tab:: cpp C++
  54. // Parent
  55. Node *node = get_node<Node>("Child");
  56. if (node != nullptr) {
  57. // Note that get_node may return a nullptr, which would make calling the connect method crash the engine if "Child" does not exist!
  58. // So unless you are 1000% sure get_node will never return a nullptr, it's a good idea to always do a nullptr check.
  59. node->connect("signal_name", callable_mp(this, &ObjectWithMethod::method_on_the_object));
  60. }
  61. // Child
  62. emit_signal("signal_name"); // Triggers parent-defined behavior.
  63. 2. Call a method. Used to start behavior.
  64. .. tabs::
  65. .. code-tab:: gdscript GDScript
  66. # Parent
  67. $Child.method_name = "do"
  68. # Child, assuming it has String property 'method_name' and method 'do'.
  69. call(method_name) # Call parent-defined method (which child must own).
  70. .. code-tab:: csharp
  71. // Parent
  72. GetNode("Child").Set("MethodName", "Do");
  73. // Child
  74. Call(MethodName); // Call parent-defined method (which child must own).
  75. .. code-tab:: cpp C++
  76. // Parent
  77. Node *node = get_node<Node>("Child");
  78. if (node != nullptr) {
  79. node->set("method_name", "do");
  80. }
  81. // Child
  82. call(method_name); // Call parent-defined method (which child must own).
  83. 3. Initialize a :ref:`Callable <class_Callable>` property. Safer than a method
  84. as ownership of the method is unnecessary. Used to start behavior.
  85. .. tabs::
  86. .. code-tab:: gdscript GDScript
  87. # Parent
  88. $Child.func_property = object_with_method.method_on_the_object
  89. # Child
  90. func_property.call() # Call parent-defined method (can come from anywhere).
  91. .. code-tab:: csharp
  92. // Parent
  93. GetNode("Child").Set("FuncProperty", Callable.From(ObjectWithMethod.MethodOnTheObject));
  94. // Child
  95. FuncProperty.Call(); // Call parent-defined method (can come from anywhere).
  96. .. code-tab:: cpp C++
  97. // Parent
  98. Node *node = get_node<Node>("Child");
  99. if (node != nullptr) {
  100. node->set("func_property", Callable(&ObjectWithMethod::method_on_the_object));
  101. }
  102. // Child
  103. func_property.call(); // Call parent-defined method (can come from anywhere).
  104. 4. Initialize a Node or other Object reference.
  105. .. tabs::
  106. .. code-tab:: gdscript GDScript
  107. # Parent
  108. $Child.target = self
  109. # Child
  110. print(target) # Use parent-defined node.
  111. .. code-tab:: csharp
  112. // Parent
  113. GetNode("Child").Set("Target", this);
  114. // Child
  115. GD.Print(Target); // Use parent-defined node.
  116. .. code-tab:: cpp C++
  117. // Parent
  118. Node *node = get_node<Node>("Child");
  119. if (node != nullptr) {
  120. node->set("target", this);
  121. }
  122. // Child
  123. UtilityFunctions::print(target);
  124. 5. Initialize a NodePath.
  125. .. tabs::
  126. .. code-tab:: gdscript GDScript
  127. # Parent
  128. $Child.target_path = ".."
  129. # Child
  130. get_node(target_path) # Use parent-defined NodePath.
  131. .. code-tab:: csharp
  132. // Parent
  133. GetNode("Child").Set("TargetPath", NodePath(".."));
  134. // Child
  135. GetNode(TargetPath); // Use parent-defined NodePath.
  136. .. code-tab:: cpp C++
  137. // Parent
  138. Node *node = get_node<Node>("Child");
  139. if (node != nullptr) {
  140. node->set("target_path", NodePath(".."));
  141. }
  142. // Child
  143. get_node<Node>(target_path); // Use parent-defined NodePath.
  144. These options hide the points of access from the child node. This in turn
  145. keeps the child **loosely coupled** to its environment. You can reuse it
  146. in another context without any extra changes to its API.
  147. .. note::
  148. Although the examples above illustrate parent-child relationships,
  149. the same principles apply towards all object relations. Nodes which
  150. are siblings should only be aware of their own hierarchies while an ancestor
  151. mediates their communications and references.
  152. .. tabs::
  153. .. code-tab:: gdscript GDScript
  154. # Parent
  155. $Left.target = $Right.get_node("Receiver")
  156. # Left
  157. var target: Node
  158. func execute():
  159. # Do something with 'target'.
  160. # Right
  161. func _init():
  162. var receiver = Receiver.new()
  163. add_child(receiver)
  164. .. code-tab:: csharp
  165. // Parent
  166. GetNode<Left>("Left").Target = GetNode("Right/Receiver");
  167. public partial class Left : Node
  168. {
  169. public Node Target = null;
  170. public void Execute()
  171. {
  172. // Do something with 'Target'.
  173. }
  174. }
  175. public partial class Right : Node
  176. {
  177. public Node Receiver = null;
  178. public Right()
  179. {
  180. Receiver = ResourceLoader.Load<Script>("Receiver.cs").New();
  181. AddChild(Receiver);
  182. }
  183. }
  184. .. code-tab:: cpp C++
  185. // Parent
  186. get_node<Left>("Left")->target = get_node<Node>("Right/Receiver");
  187. class Left : public Node {
  188. GDCLASS(Left, Node)
  189. protected:
  190. static void _bind_methods() {}
  191. public:
  192. Node *target = nullptr;
  193. Left() {}
  194. void execute() {
  195. // Do something with 'target'.
  196. }
  197. };
  198. class Right : public Node {
  199. GDCLASS(Right, Node)
  200. protected:
  201. static void _bind_methods() {}
  202. public:
  203. Node *receiver = nullptr;
  204. Right() {
  205. receiver = memnew(Node);
  206. add_child(receiver);
  207. }
  208. };
  209. The same principles also apply to non-Node objects that maintain dependencies
  210. on other objects. Whichever object owns the other objects should manage
  211. the relationships between them.
  212. .. warning::
  213. You should favor keeping data in-house (internal to a scene), though, as
  214. placing a dependency on an external context, even a loosely coupled one,
  215. still means that the node will expect something in its environment to be
  216. true. The project's design philosophies should prevent this from happening.
  217. If not, the code's inherent liabilities will force developers to use
  218. documentation to keep track of object relations on a microscopic scale; this
  219. is otherwise known as development hell. Writing code that relies on external
  220. documentation to use it safely is error-prone by default.
  221. To avoid creating and maintaining such documentation, you convert the
  222. dependent node ("child" above) into a tool script that implements
  223. ``_get_configuration_warnings()``.
  224. Returning a non-empty PackedStringArray from it will make the Scene dock generate a
  225. warning icon with the string(s) as a tooltip by the node. This is the same icon
  226. that appears for nodes such as the
  227. :ref:`Area2D <class_Area2D>` node when it has no child
  228. :ref:`CollisionShape2D <class_CollisionShape2D>` nodes defined. The editor
  229. then self-documents the scene through the script code. No content duplication
  230. via documentation is necessary.
  231. A GUI like this can better inform project users of critical information about
  232. a Node. Does it have external dependencies? Have those dependencies been
  233. satisfied? Other programmers, and especially designers and writers, will need
  234. clear instructions in the messages telling them what to do to configure it.
  235. So, why does all this complex switcheroo work? Well, because scenes operate
  236. best when they operate alone. If unable to work alone, then working with
  237. others anonymously (with minimal hard dependencies, i.e. loose coupling)
  238. is the next best thing. Inevitably, changes may need to be made to a class, and
  239. if these changes cause it to interact with other scenes in unforeseen ways,
  240. then things will start to break down. The whole point of all this indirection
  241. is to avoid ending up in a situation where changing one class results in
  242. adversely affecting other classes dependent on it.
  243. Scripts and scenes, as extensions of engine classes, should abide
  244. by *all* OOP principles. Examples include...
  245. - `SOLID <https://en.wikipedia.org/wiki/SOLID>`_
  246. - `DRY <https://en.wikipedia.org/wiki/Don%27t_repeat_yourself>`_
  247. - `KISS <https://en.wikipedia.org/wiki/KISS_principle>`_
  248. - `YAGNI <https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it>`_
  249. Choosing a node tree structure
  250. ------------------------------
  251. You might start to work on a game but get overwhelmed by the vast possibilities
  252. before you. You might know what you want to do, what systems you want to
  253. have, but *where* do you put them all? How you go about making your game
  254. is always up to you. You can construct node trees in countless ways.
  255. If you are unsure, this guide can give you a sample of a decent structure to
  256. start with.
  257. A game should always have an "entry point"; somewhere you can definitively
  258. track where things begin so that you can follow the logic as it continues
  259. elsewhere. It also serves as a bird's eye view of all other data and logic
  260. in the program. For traditional applications, this is normally a "main"
  261. function. In Godot, it's a Main node.
  262. - Node "Main" (main.gd)
  263. The ``main.gd`` script will serve as the primary controller of your game.
  264. Then you have an in-game "World" (a 2D or 3D one). This can be a child
  265. of Main. In addition, you will need a primary GUI for your game that manages
  266. the various menus and widgets the project needs.
  267. - Node "Main" (main.gd)
  268. - Node2D/Node3D "World" (game_world.gd)
  269. - Control "GUI" (gui.gd)
  270. When changing levels, you can then swap out the children of the "World" node.
  271. :ref:`Changing scenes manually <doc_change_scenes_manually>` gives you full
  272. control over how your game world transitions.
  273. The next step is to consider what gameplay systems your project requires.
  274. If you have a system that...
  275. 1. tracks all of its data internally
  276. 2. should be globally accessible
  277. 3. should exist in isolation
  278. ... then you should create an :ref:`autoload 'singleton' node <doc_singletons_autoload>`.
  279. .. note::
  280. For smaller games, a simpler alternative with less control would be to have
  281. a "Game" singleton that simply calls the
  282. :ref:`SceneTree.change_scene_to_file() <class_SceneTree_method_change_scene_to_file>` method
  283. to swap out the main scene's content. This structure more or less keeps
  284. the "World" as the main game node.
  285. Any GUI would also need to be either a singleton, a transitory part of the
  286. "World", or manually added as a direct child of the root. Otherwise, the
  287. GUI nodes would also delete themselves during scene transitions.
  288. If you have systems that modify other systems' data, you should define those as
  289. their own scripts or scenes, rather than autoloads. For more information, see
  290. :ref:`Autoloads versus regular nodes <doc_autoloads_versus_internal_nodes>`.
  291. Each subsystem within your game should have its own section within the
  292. SceneTree. You should use parent-child relationships only in cases where nodes
  293. are effectively elements of their parents. Does removing the parent reasonably
  294. mean that the children should also be removed? If not, then it should have its
  295. own place in the hierarchy as a sibling or some other relation.
  296. .. note::
  297. In some cases, you need these separated nodes to *also* position themselves
  298. relative to each other. You can use the
  299. :ref:`RemoteTransform <class_RemoteTransform3D>` /
  300. :ref:`RemoteTransform2D <class_RemoteTransform2D>` nodes for this purpose.
  301. They will allow a target node to conditionally inherit selected transform
  302. elements from the Remote\* node. To assign the ``target``
  303. :ref:`NodePath <class_NodePath>`, use one of the following:
  304. 1. A reliable third party, likely a parent node, to mediate the assignment.
  305. 2. A group, to pull a reference to the desired node (assuming there
  306. will only ever be one of the targets).
  307. When you should do this is subjective. The dilemma arises when you must
  308. micro-manage when a node must move around the SceneTree to preserve
  309. itself. For example...
  310. - Add a "player" node to a "room".
  311. - Need to change rooms, so you must delete the current room.
  312. - Before the room can be deleted, you must preserve and/or move the player.
  313. If memory is not a concern, you can...
  314. - Create the new room.
  315. - Move the player to the new room.
  316. - Delete the old room.
  317. If memory is a concern, instead you will need to...
  318. - Move the player somewhere else in the tree.
  319. - Delete the room.
  320. - Instantiate and add the new room.
  321. - Re-add the player to the new room.
  322. The issue is that the player here is a "special case" where the
  323. developers must *know* that they need to handle the player this way for the
  324. project. The only way to reliably share this information as a team
  325. is to *document* it. Keeping implementation details in documentation is
  326. dangerous. It's a maintenance burden, strains code readability, and
  327. unnecessarily bloats the intellectual content of a project.
  328. In a more complex game with larger assets, it can be a better idea to keep
  329. the player somewhere else in the SceneTree entirely. This results in:
  330. 1. More consistency.
  331. 2. No "special cases" that must be documented and maintained somewhere.
  332. 3. No opportunity for errors to occur because these details are not accounted
  333. for.
  334. In contrast, if you ever need a child node that does *not* inherit
  335. the transform of its parent, you have the following options:
  336. 1. The **declarative** solution: place a :ref:`Node <class_Node>` in between
  337. them. Since it doesn't have a transform, they won't pass this information
  338. to its children.
  339. 2. The **imperative** solution: Use the ``top_level`` property for the
  340. :ref:`CanvasItem <class_CanvasItem_property_top_level>` or
  341. :ref:`Node3D <class_Node3D_property_top_level>` node. This will make
  342. the node ignore its inherited transform.
  343. .. note::
  344. If building a networked game, keep in mind which nodes and gameplay systems
  345. are relevant to all players versus those just pertinent to the authoritative
  346. server. For example, users do not all need to have a copy of every players'
  347. "PlayerController" logic - they only need their own. Keeping them in a
  348. separate branch from the "world" can help simplify the management of game
  349. connections and the like.
  350. The key to scene organization is to consider the SceneTree in relational terms
  351. rather than spatial terms. Are the nodes dependent on their parent's existence?
  352. If not, then they can thrive all by themselves somewhere else.
  353. If they are dependent, then it stands to reason that they should be children of
  354. that parent (and likely part of that parent's scene if they aren't already).
  355. Does this mean nodes themselves are components? Not at all.
  356. Godot's node trees form an aggregation relationship, not one of composition.
  357. But while you still have the flexibility to move nodes around, it is still best
  358. when such moves are unnecessary by default.