<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: christine</title>
    <description>The latest articles on Forem by christine (@christinec_dev).</description>
    <link>https://forem.com/christinec_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F688776%2F969c8499-4199-4c4a-a5a2-84cc4d8454ee.jpg</url>
      <title>Forem: christine</title>
      <link>https://forem.com/christinec_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/christinec_dev"/>
    <language>en</language>
    <item>
      <title>Godot 4: The Book of Code</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Sun, 26 Oct 2025 17:57:52 +0000</pubDate>
      <link>https://forem.com/christinec_dev/godot-4-the-book-of-code-jop</link>
      <guid>https://forem.com/christinec_dev/godot-4-the-book-of-code-jop</guid>
      <description>&lt;p&gt;If you’re eager to dive into the exciting world of Godot development, it’s important to get a handle on the basics of programming! You don’t need to be a coding wizard to make a game, you just need to have a solid understanding the key concepts like variables, functions, loops, and arrays.&lt;/p&gt;

&lt;p&gt;I previously put together the &lt;a href="https://oops-i-devd.gitbook.io/christinec-dev/free-resources/godot-book-of-nodes" rel="noopener noreferrer"&gt;&lt;strong&gt;Book of Nodes&lt;/strong&gt;&lt;/a&gt; (which I’m currently updating), covering the common nodes you’ll encounter on your game development journey. I thought it would be super helpful to create a companion resource — a friendly coding guide!&lt;/p&gt;

&lt;p&gt;This guide covers the fundamentals of coding in Godot. We won’t delve into all the aspects of coding or GDScript, but we will cover the core structures necessary to begin coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is GDScript?
&lt;/h2&gt;

&lt;p&gt;GDScript is Godot’s own programming language, made &lt;em&gt;just for games&lt;/em&gt;. It’s easy to read, beginner-friendly, and designed to integrate tightly with the Godot Editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why use GDScript?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s simple, fast, and built for Godot.&lt;/li&gt;
&lt;li&gt;It’s similar to Python (clean syntax, no extra symbols).&lt;/li&gt;
&lt;li&gt;You can write code directly on any node to control how it behaves &lt;strong&gt;.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A lot of developers switch over from Unity and therefore codes in Godot using &lt;strong&gt;C#&lt;/strong&gt;. For that reason, we will be covering both GDScript and C# in this resource.&lt;/p&gt;




&lt;h2&gt;
  
  
  Navigation
&lt;/h2&gt;

&lt;p&gt;This resource is broken down into the following sections:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Fundamentals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Data Types&lt;/li&gt;
&lt;li&gt;Constants&lt;/li&gt;
&lt;li&gt;Functions&lt;/li&gt;
&lt;li&gt;Comments&lt;/li&gt;
&lt;li&gt;Scope&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Logic &amp;amp; Control
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If / Else&lt;/li&gt;
&lt;li&gt;Match (Switch)&lt;/li&gt;
&lt;li&gt;Loops (For / While)&lt;/li&gt;
&lt;li&gt;Break, Continue, &amp;amp; Return&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Collections
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;Dictionaries&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Gameplay Mechanics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Signals (Events)&lt;/li&gt;
&lt;li&gt;Input&lt;/li&gt;
&lt;li&gt;Timers&lt;/li&gt;
&lt;li&gt;Physics Process vs. Process&lt;/li&gt;
&lt;li&gt;Random Numbers&lt;/li&gt;
&lt;li&gt;The Ready Function&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Object &amp;amp; Scene Control
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Instancing Scenes&lt;/li&gt;
&lt;li&gt;Accessing Nodes&lt;/li&gt;
&lt;li&gt;Inheritance&lt;/li&gt;
&lt;li&gt;Export Variables&lt;/li&gt;
&lt;li&gt;Groups&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Bonus: Polish &amp;amp; Organization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Code Style Tips&lt;/li&gt;
&lt;li&gt;Debugging&lt;/li&gt;
&lt;li&gt;Autoloads (Singletons)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make it easier to read, you can download the (free) &lt;strong&gt;Offline PDF&lt;/strong&gt; version of this post &lt;a href="https://ko-fi.com/s/e90ca02be7" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vroaxc2c7rlkgidoyui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vroaxc2c7rlkgidoyui.png" alt="Godot 4 Book of Code" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Part I: Fundamentals
&lt;/h1&gt;

&lt;p&gt;Before embarking on a complex project, it’s crucial to grasp the foundational elements of coding. The Fundamentals section covers the core concepts that you will frequently use in nearly every Godot script. These principles form the basis of all programming, not just within Godot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this section, we will cover the following topics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;In this section, we will cover the following topics:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#variables" rel="noopener noreferrer"&gt;&lt;strong&gt;Variables&lt;/strong&gt;  &lt;/a&gt;— storing and reusing data&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#built-in-types" rel="noopener noreferrer"&gt;&lt;strong&gt;Data Types&lt;/strong&gt;&lt;/a&gt; — understanding different kinds of information&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#constants" rel="noopener noreferrer"&gt;&lt;strong&gt;Constants&lt;/strong&gt;  &lt;/a&gt;— setting fixed, unchanging values&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#functions" rel="noopener noreferrer"&gt;&lt;strong&gt;Functions&lt;/strong&gt;  &lt;/a&gt;— organizing your logic into reusable actions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#comments" rel="noopener noreferrer"&gt;&lt;strong&gt;Comments&lt;/strong&gt;&lt;/a&gt; — explaining your code for yourself and others&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://school.gdquest.com/glossary/scope" rel="noopener noreferrer"&gt;&lt;strong&gt;Scope &lt;/strong&gt;&lt;/a&gt;— understanding where and how your data exists&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Variables
&lt;/h2&gt;

&lt;p&gt;Variables are containers used to store reusable pieces of data such as numbers, text, or even entire nodes. You can think of them as your code’s “memory slots,” holding information like the player’s name, health, or the sound that plays when they take damage.&lt;/p&gt;

&lt;p&gt;Variables can be defined globally, making them accessible in every piece of the script (and sometimes other scripts), or locally, within functions, where they exist only while that function runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclzfibj4ht4s4tu274ra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclzfibj4ht4s4tu274ra.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Variables are Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Games constantly track information:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Player health, score, or ammo&lt;/li&gt;
&lt;li&gt;Enemy positions&lt;/li&gt;
&lt;li&gt;Whether a door is open or not&lt;/li&gt;
&lt;li&gt;The name of the NPC you’re talking to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without variables, a game wouldn’t know what happened before or what should happen next. It couldn’t reference or change values , making it impossible to keep track of states. Variables are the backbone of all programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;variable_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="n"&gt;variableName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use clear, descriptive names&lt;/strong&gt;  — for example, player_health or enemy_speed, so it’s easy to understand what each variable represents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow snake_case naming in GDScript&lt;/strong&gt;  — write variable names in lowercase with underscores, like player_score or door_open.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow camelCase naming in C#&lt;/strong&gt;  — write variable names in camel case, like playerScore or doorOpen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid reserved keywords&lt;/strong&gt;  — don’t use words that Godot or GDScript already reserve for internal use (e.g. name, class, print), as this can cause errors or unexpected behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might define variables throughout your game.&lt;/p&gt;

&lt;p&gt;The below code creates a player with the name “Bob”, who has 100 health and a sword.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;has_sword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;playerName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;hasSword&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Data Types
&lt;/h2&gt;

&lt;p&gt;Data types define the kind of information that a variable can store, such as numbers, text, boolean values (true/false), or even complex objects like nodes or images. They are essential for ensuring that your game can correctly utilize and process data while maintaining a standardized approach to handling and processing that data.&lt;/p&gt;

&lt;p&gt;For example, by specifying the data type, we can prevent the addition of a string to a numeric data type. This means that you cannot assign “Bob” as a value for your health; it must always be a number or a float!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Data Types Are Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Every game needs to handle different kinds of information:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Numbers:&lt;/strong&gt; Used for health, speed, or score. These can be either &lt;em&gt;integers&lt;/em&gt; (whole numbers like 1 or 99) or &lt;em&gt;floats&lt;/em&gt; (decimal values, such as 1.42 or 9.87).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text:&lt;/strong&gt; Refers to player names, dialogues, or menus. Text is defined as &lt;em&gt;strings&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boolean Values:&lt;/strong&gt; Represent true/false states, such as “Is the door open?” or “Is the player jumping?”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Types:&lt;/strong&gt; Include structures like &lt;em&gt;Vector2&lt;/em&gt;, &lt;em&gt;Color&lt;/em&gt;, or &lt;em&gt;Node&lt;/em&gt;, which are used for movement, visual representation, and object references.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without data types, your game wouldn’t know how to compare, process, calculate, or display information properly. This could potentially lead to to confusing bugs and broken logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of Data
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulu1aqtf6hbo6rxtfltv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulu1aqtf6hbo6rxtfltv.png" alt="Godot 4 Book of Code" width="800" height="1353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;variable_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;variableName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;playerSpeed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;4.5f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always use the correct type for what you’re storing — &lt;/strong&gt; use integers (int) for whole numbers, floats (float) for decimals, and strings (String) for text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be consistent — &lt;/strong&gt; don’t change a variable’s type mid-script (e.g., storing a number and later replacing it with text).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use type hints&lt;/strong&gt; (GDScript 2.0+) &lt;strong&gt;or explicit types&lt;/strong&gt; (C#) to make your code safer and easier to read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn Godot’s built-in types&lt;/strong&gt;  — like Vector2, Vector3, Color, Node, and Array, as they’re core to building any game.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might define different data types for a player’s stats and position.&lt;/p&gt;

&lt;p&gt;The below code creates a player with a name of “Bob” (value of string), a health of 100 and speed of 4.5 (numeric values), a sword (boolean), and position (Vector2).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;#string
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="c1"&gt;#integer
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt; &lt;span class="c1"&gt;#float
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;has_sword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;#boolean
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# complex type
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;playerName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//string&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//integer&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;playerSpeed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;4.5f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//float&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;hasSword&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//boolean&lt;/span&gt;
&lt;span class="n"&gt;Vector2&lt;/span&gt; &lt;span class="n"&gt;playerPosition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//complex type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Constants
&lt;/h2&gt;

&lt;p&gt;Constants are values that never change while your game runs. They’re like permanent markers in your code — once defined, they stay the same no matter what happens.&lt;/p&gt;

&lt;p&gt;You might use constants for things like maximum health, gravity, default speed, or level names. These are all values that should stay fixed and not be altered during gameplay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faecvb26bq2m2o4hrl9p2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faecvb26bq2m2o4hrl9p2.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Constants Are Needed
&lt;/h3&gt;

&lt;p&gt;Constants make your code more organized, predictable, and easier to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They’re especially useful for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed values that should never change, like MAX_HEALTH = 100 (we want our health to change, but never go over 100%)&lt;/li&gt;
&lt;li&gt;Game settings like gravity, jump force, or map size&lt;/li&gt;
&lt;li&gt;Avoiding “magic numbers” — instead of random hard-coded numbers, you give them clear names&lt;/li&gt;
&lt;li&gt;Preventing accidental changes to important values during gameplay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without constants, you might end up reusing the same number in multiple places, and if you ever need to change it, you’ll have to hunt it down everywhere in your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CONSTANT_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MAX_HEALTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;CONSTANT_NAME&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MAX_HEALTH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use constants for fixed or shared values&lt;/strong&gt;  — especially ones that appear multiple times in your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name constants in ALL_CAPS&lt;/strong&gt; to make them stand out (e.g., MAX_SPEED, GRAVITY).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group related constants together&lt;/strong&gt; at the top of your script for better organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never modify a constant&lt;/strong&gt;  &lt;strong&gt;after it’s defined&lt;/strong&gt; in your code. That defeats its purpose, so if you define it at the beginning of your code, avoid modifying its value later in a function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might define constants for player attributes and physics.&lt;/p&gt;

&lt;p&gt;The code below creates constants that ensure the maximum health never surpasses 100%, sets a gravity force of 9.8, assigns the final player name as Bob, and establishes a spawn position that will never change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MAX_HEALTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;GRAVITY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;9.8&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PLAYER_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;START_POSITION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MAX_HEALTH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;GRAVITY&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;9.8f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;PLAYER_NAME&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt; &lt;span class="n"&gt;START_POSITION&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h38ane3xvwqdr2q1eae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h38ane3xvwqdr2q1eae.png" alt="Godot 4 Book of Code" width="800" height="93"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Functions
&lt;/h2&gt;

&lt;p&gt;Functions are reusable blocks of code that perform specific tasks. They let you organize your logic into smaller, manageable pieces, almost like instructions you can call at anytime.&lt;/p&gt;

&lt;p&gt;Think of a function as a mini-program inside your script: instead of writing the same code over and over, you define it once and &lt;em&gt;call&lt;/em&gt; it whenever needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynr27wa7z2mvd876ypza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynr27wa7z2mvd876ypza.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Functions Are Needed
&lt;/h3&gt;

&lt;p&gt;Games rely on repeated actions and logic. For example, an NPC should know when to walk and when to stop. Functions make that process clean and efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moving a character&lt;/li&gt;
&lt;li&gt;Playing a sound when the player takes damage&lt;/li&gt;
&lt;li&gt;Spawning an enemy or item&lt;/li&gt;
&lt;li&gt;Saving or loading game data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without functions, you’d need to duplicate the same lines of code in multiple places — making your game harder to read, debug, and maintain. Functions promote clean, modular, and reusable code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# code to run
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;ReturnType&lt;/span&gt; &lt;span class="nf"&gt;FunctionName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code to run&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use clear, action-based names&lt;/strong&gt; (e.g., move_player(), take_damage(), play_music()), so it’s obvious what the function does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep functions focused&lt;/strong&gt;  — each one should do &lt;em&gt;one thing well&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use parameters&lt;/strong&gt; to pass data into a function, and returns to get data back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid long functions&lt;/strong&gt;  — break them into smaller pieces for readability and reuse.&lt;/li&gt;
&lt;li&gt;In GDScript, function names use snake_case; in C#, use PascalCase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;The code defines a variable which stores the player’s health, and in the function, whenever the player takes damage, the health value changes. Thus, the function controls the logic for when the player takes damage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# variable
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="c1"&gt;# function to change variable
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player health:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// variable&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// function to change variable&lt;/span&gt;
&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TakeDamage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player health: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Comments
&lt;/h2&gt;

&lt;p&gt;Comments are notes that you leave inside your code that the computer completely ignores. They’re meant for &lt;em&gt;you&lt;/em&gt; and other developers to explain what your code does, why you wrote it that way, or to temporarily disable certain lines during testing.&lt;/p&gt;

&lt;p&gt;Think of comments as sticky notes for your future self. They help make your code readable, teachable, and easier to maintain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2imcha9r5glbhyg1ey8h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2imcha9r5glbhyg1ey8h.jpg" alt="Godot 4 Book of Code" width="559" height="728"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Comments Are Needed
&lt;/h3&gt;

&lt;p&gt;As you grow your game, your code may become confusing after a few weeks (or to someone new reading it). Comments help you remember the &lt;em&gt;reasoning&lt;/em&gt; behind your decisions, and take notes on what you need to change or refer back to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You might use comments to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explain what a function or variable does&lt;/li&gt;
&lt;li&gt;Clarify complex logic or math&lt;/li&gt;
&lt;li&gt;Leave notes for future improvements&lt;/li&gt;
&lt;li&gt;Temporarily disable code without deleting it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without comments, your codebase can quickly become a maze of unexplained logic — especially in large projects with multiple scripts and systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GDScript
# Single-line comment
# This explains a line of code
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CSharp &lt;/span&gt;
&lt;span class="c1"&gt;// Single-line comment&lt;/span&gt;
&lt;span class="cm"&gt;/* Multi-line
   comment */&lt;/span&gt;
&lt;span class="c1"&gt;// This explains a line of code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write comments for clarity, not decoration.&lt;/strong&gt; Use them to explain &lt;em&gt;why&lt;/em&gt; something exists, not just &lt;em&gt;what&lt;/em&gt; it does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep comments up to date.&lt;/strong&gt; Outdated comments can be more confusing than no comments at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use comments to break your code into sections.&lt;/strong&gt; It helps you navigate long scripts easily.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;GDScript&lt;/strong&gt; , &lt;strong&gt;comments&lt;/strong&gt; start with #.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;C#&lt;/strong&gt; , &lt;strong&gt;comments&lt;/strong&gt; start with //.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use comments to explain your code in both languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Player starts with 100 health
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;  

&lt;span class="c1"&gt;# Function to apply damage to the player
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player health:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Debug print to console
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Player starts with 100 health&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* Function to apply damage
   and display remaining health */&lt;/span&gt;
&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TakeDamage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player health: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Debug print&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Scope
&lt;/h2&gt;

&lt;p&gt;Scope determines where a variable or function can be accessed in your code. It’s like defining whether a certain piece of logic is available everywhere or only inside a specific block of code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9nzktsdxmdgxfvzvxfge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9nzktsdxmdgxfvzvxfge.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Scope Is Needed
&lt;/h3&gt;

&lt;p&gt;Scope keeps your code clean, predictable, and safe from unwanted changes.&lt;/p&gt;

&lt;p&gt;In games, you might want some data to be accessible everywhere (like the player’s score), while other data should only exist temporarily inside a function (like a loop counter or a temporary position).&lt;/p&gt;

&lt;p&gt;Without scope rules, variables could overwrite each other, cause bugs, or leak data across scripts unintentionally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s the most common scopes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Global scope:&lt;/strong&gt; Variables and functions that can be accessed from anywhere in the script, and sometimes by other scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local scope:&lt;/strong&gt; Variables that only exist inside a specific function or block. They’re created when the function runs and destroyed when it ends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access modifiers (C# only):&lt;/strong&gt; Define who can access a variable or function from other scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjfto5n31k4atq2iunsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjfto5n31k4atq2iunsu.png" alt="Godot 4 Book of Code" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Global variable
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;global_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;local_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="c1"&gt;# Local to this function - you cannot call it outside of here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Global variable&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;globalVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SomeFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;localVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Only accessible inside this function&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Access modifiers (C# only)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;localVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible by all scripts&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;localVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible only in this class&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;localVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible in this class and subclasses&lt;/span&gt;
&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;localVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible within the same assembly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use local scope whenever possible&lt;/strong&gt;  — it keeps variables self-contained and prevents accidental changes elsewhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use global scope only for shared data&lt;/strong&gt; like settings, player stats, or managers that must be accessed by multiple scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid naming conflicts&lt;/strong&gt;  — two variables with the same name in different scopes can cause confusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In GDScript&lt;/strong&gt; , define globals outside of functions (like at the top of your script), and locals inside.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In C#&lt;/strong&gt; , use access modifiers like public, private, and protected to control visibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s a simple example showing the difference between global and local scope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Global variable - any function can access this, even other scripts
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Local variable (only exists while this function runs)
&lt;/span&gt;    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;new_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;After damage:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Global variable - any function can access this, even other scripts&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible by all scripts&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ammoCount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible only in this class&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;armor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible in this class and subclasses&lt;/span&gt;
&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessible within the same assembly&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TakeDamage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Local variable (only exists within this function)&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;newHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After damage: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;newHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Part II: Logic &amp;amp; Control
&lt;/h1&gt;

&lt;p&gt;Games and programs are filled with decisions — should the player take damage? Should the door open? Should the enemy chase or retreat?&lt;/p&gt;

&lt;p&gt;Logic and control structures enable your game to think, react, and adapt to various situations. These tools instruct your code on what actions to take and when to take them. They serve as the brain behind your game’s behavior, controlling the flow of the game, responding to player input, and determining outcomes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this section, we will explore the following concepts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#if-else-elif" rel="noopener noreferrer"&gt;&lt;strong&gt;If / Else&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Making choices&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#match" rel="noopener noreferrer"&gt;&lt;strong&gt;Match (Switch)&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Handling multiple possibilities&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#match" rel="noopener noreferrer"&gt;&lt;strong&gt;Loops (For / While)&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Repeating actions efficiently&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Break, Return, &amp;amp; Continue&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;:&lt;/strong&gt; Controlling loop &amp;amp; function behavior&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. If / Else
&lt;/h2&gt;

&lt;p&gt;If / Else statements are the foundation of decision-making in programming. They let your game choose different paths depending on whether certain conditions are true or false.&lt;/p&gt;

&lt;p&gt;You can think of them like branching roads — your game checks a condition, and depending on the result, it takes one route or another.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9x96j9xpmj34gbcrkite.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9x96j9xpmj34gbcrkite.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why If / Else Is Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Every game relies on conditions, for example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the player’s health reaches zero → trigger game over&lt;/li&gt;
&lt;li&gt;If the score is high enough → unlock a new level&lt;/li&gt;
&lt;li&gt;If a key is collected → open a door&lt;/li&gt;
&lt;li&gt;If the player presses jump → play jump animation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without conditional logic, your game would run in a straight line with no reaction to what happens — no decisions, no consequences, and no interactivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# code
&lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;other_condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# code
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# code
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otherCondition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep conditions clear and readable&lt;/strong&gt;  — use descriptive variable names so your logic reads like a sentence (if player_health &amp;lt;= 0:).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid deep nesting&lt;/strong&gt;  — too many nested if statements make code hard to follow. Consider using match or early returns instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use elif for multiple related conditions&lt;/strong&gt; instead of chaining separate ifs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test edge cases&lt;/strong&gt;  — ensure your logic works at boundaries (e.g., 0 health, max score).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s a simple block of code that uses if/else statements to determine whether the player is alive, low on health, or defeated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;

&lt;span class="c1"&gt;# If health is more than zero, the player is alive.
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player is alive!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# If health is between 1 and 50, warn that it's low.
&lt;/span&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player health low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Otherwise, the player is defeated.
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player is defeated.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// If health is more than zero, the player is alive.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player is alive!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// If health is between 1 and 50, warn that it's low.&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player health low"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Otherwise, the player is defeated.&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player is defeated."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkotvjdu568m36l7d1hll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkotvjdu568m36l7d1hll.png" alt="Godot 4 Book of Code" width="800" height="66"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Match (Switch)
&lt;/h2&gt;

&lt;p&gt;The Match statement (called &lt;strong&gt;Switch&lt;/strong&gt; in many other languages) is a cleaner, more organized way to handle multiple possible outcomes for a single value.&lt;/p&gt;

&lt;p&gt;Instead of writing a long chain of if and elif statements, match lets your code check one variable against several conditions, thus keeping your logic simple and easy to read.&lt;/p&gt;

&lt;p&gt;Think of it like a menu of possibilities: the program picks the one that matches and runs the code for that case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1o2fclssgpyxhfbfmz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1o2fclssgpyxhfbfmz7.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Match Is Needed
&lt;/h3&gt;

&lt;p&gt;When your game needs to react differently to multiple options — such as player input, item types, or enemy states — match keeps your logic tidy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checking which key was pressed&lt;/li&gt;
&lt;li&gt;Determining what item the player picked up&lt;/li&gt;
&lt;li&gt;Reacting to an enemy’s state (idle, chasing, attacking)&lt;/li&gt;
&lt;li&gt;Handling dialog choices or menu selections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without match, you’d end up with repetitive if/elif blocks that are harder to maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;pattern1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# code
&lt;/span&gt;    &lt;span class="n"&gt;pattern2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# code
&lt;/span&gt;    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# default case
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;pattern1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// code&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;pattern2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// code&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// default case&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use match for clear, single-variable comparisons&lt;/strong&gt;  — it’s cleaner than stacking if/elif.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include a _ (default) case&lt;/strong&gt; to catch unexpected values or errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep cases short and direct&lt;/strong&gt;  — avoid nesting too much logic inside each one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In C#&lt;/strong&gt; , use the switch statement (and consider switch expressions in newer C# versions for concise code).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use match to handle player actions. The logic of the game will change depending on the state of the player.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Player state
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jump&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Change state based on action
&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player attacks!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jump&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player jumps!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;block&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player blocks!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown action!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Player state&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jump"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Change state based on action&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"attack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player attacks!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"jump"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player jumps!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player blocks!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unknown action!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfzjz3qhm9ub1pvgmpuz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfzjz3qhm9ub1pvgmpuz.png" alt="Godot 4 Book of Code" width="800" height="65"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Loops (For / While)
&lt;/h2&gt;

&lt;p&gt;Loops allow your code to repeat actions automatically without writing the same line over and over. They’re essential for anything that needs to run multiple times — like moving enemies, checking objects, or counting through a list.&lt;/p&gt;

&lt;p&gt;Think of loops as automated cycles: you define &lt;em&gt;what&lt;/em&gt; should happen and &lt;em&gt;how long&lt;/em&gt; it should continue&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fminls1b53mkn3nadrfd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fminls1b53mkn3nadrfd1.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Loops Are Needed
&lt;/h3&gt;

&lt;p&gt;Games rely on repetition — from drawing frames to checking collisions. Loops make that process simple and efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You might use them to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move every enemy in a list&lt;/li&gt;
&lt;li&gt;Spawn several coins or projectiles&lt;/li&gt;
&lt;li&gt;Update player stats each frame&lt;/li&gt;
&lt;li&gt;Repeat something until a condition is met&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without loops, you’d have to manually duplicate code for every instance — wasting time and creating room for errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fpn0zr998rzk0oedwrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fpn0zr998rzk0oedwrz.png" alt="Godot 4 Book of Code" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# repeated code
&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# repeated code
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// repeated code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// repeated code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use for loops&lt;/strong&gt; when you know how many times something should run (e.g., counting or iterating through arrays).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use while loops&lt;/strong&gt; when you don’t know how long something will continue (e.g., waiting for an event or condition).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid infinite loops&lt;/strong&gt;  — always include a clear condition or break.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use descriptive loop variables&lt;/strong&gt; (for enemy in enemies: instead of for i in range(…)).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep loop bodies small&lt;/strong&gt;  — too much logic inside can hurt performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use both types of loops to manage enemies in a scene.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;for loop&lt;/strong&gt; will iterate over a list of enemies (Goblin, Orc, and Troll), and for each enemy, it will print a message indicating that they are ready to attack.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;while loop&lt;/strong&gt; will decrease the player’s health as long as their current health is more than 0. Once the player’s health reaches 0, the loop will stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Array of enemies
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Goblin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Orc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Troll&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# FOR LOOP: Go through a list of enemies
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is ready to attack!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# WHILE LOOP: Reduce player health over time
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player health:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Array of enemies&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Goblin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Orc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Troll"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// FOR LOOP: Go through a list of enemies&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is ready to attack!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// WHILE LOOP: Reduce player health over time&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player health: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvl7fgma74gh97e4sxmvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvl7fgma74gh97e4sxmvw.png" alt="Godot 4 Book of Code" width="800" height="92"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Break, Continue, &amp;amp; Return
&lt;/h2&gt;

&lt;p&gt;Inside loops and functions, &lt;strong&gt;break, continue&lt;/strong&gt; , and &lt;strong&gt;return&lt;/strong&gt; are special keywords that give you precise control over how and when your code stops or skips certain actions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;break&lt;/strong&gt;  — immediately stops a &lt;strong&gt;loop&lt;/strong&gt; , even if it hasn’t finished all its cycles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;continue&lt;/strong&gt;  — skips the rest of the &lt;strong&gt;current&lt;/strong&gt; loop cycle and jumps to the next one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;return&lt;/strong&gt;  — exits a &lt;strong&gt;function&lt;/strong&gt; immediately and optionally sends a value back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of them as &lt;strong&gt;traffic signs&lt;/strong&gt; for your logic flow: “Stop here,” “Skip ahead,” or “Exit and report back.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Why They’re Needed
&lt;/h3&gt;

&lt;p&gt;Games constantly run logic loops and functions that depend on changing conditions. These keywords give you fine-grained control over &lt;em&gt;when&lt;/em&gt; that logic should stop, skip, or exit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You might use them to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;break&lt;/strong&gt; when you’ve found the first matching item in a list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;continue&lt;/strong&gt; to skip inactive enemies or irrelevant data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;return&lt;/strong&gt; to exit a function early (like when the player is already dead)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save performance&lt;/strong&gt; by stopping unnecessary calculations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without these control statements, loops and functions would run to completion every time — wasting cycles and cluttering logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c1"&gt;# Exit loop immediately
&lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="c1"&gt;# Skip to next loop iteration
&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="c1"&gt;# Exit function and return value
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Exit loop immediately&lt;/span&gt;
&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Skip to next loop iteration&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Exit function and return value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use break only when needed&lt;/strong&gt; to exit loops early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use continue for filtering logic&lt;/strong&gt; , such as skipping invalid data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use return for early exits in functions&lt;/strong&gt; , especially for edge-case checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid multiple returns&lt;/strong&gt; in long functions — too many can make code flow harder to follow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep conditions clear and simple&lt;/strong&gt; to prevent confusion when jumping out of loops or functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might combine all three in a single gameplay function.&lt;/p&gt;

&lt;p&gt;In the code below, we loop through our list of enemies. If we encounter an invalid enemy, we use the continue statement to skip to the next iteration. If we find an Orc in the list, we print a message and continue with the remaining logic (checking for dragon). If we come across a dragon, we print a message and exit the loop using the break statement. Once the loop is complete, we return, which stops the function from executing further.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;find_enemy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="c1"&gt;# Skip missing entries
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Orc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ignoring Orc.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="c1"&gt;# Skip missing entries
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dragon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Boss found! Stopping search.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="c1"&gt;# Stop loop
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Spotted:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search complete.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# Exit function and return a message
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;FindEnemy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Skip missing entries&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Orc"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ignoring Orc."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Skip missing entries&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Dragon"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Boss found! Stopping search."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Stop loop&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Spotted: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Search complete."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Exit function and return a message&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Part III: Collections
&lt;/h1&gt;

&lt;p&gt;As your games develop, you’ll soon realize that single variables, like player_name and enemy, aren’t sufficient. You will need ways to store, organize, and manage groups of data, such as multiple enemies, items, or lines of dialogue.&lt;/p&gt;

&lt;p&gt;Collections are special data structures that enable you to handle many values simultaneously, making your scripts more dynamic, efficient, and powerful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this section, we’ll cover:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_array.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Arrays&lt;/strong&gt;  &lt;/a&gt;— ordered lists of values&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_dictionary.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Dictionaries&lt;/strong&gt;  &lt;/a&gt;— key-value pairs for labelled data&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_resource.html#description" rel="noopener noreferrer"&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/a&gt; — saved or reusable data objects&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Arrays
&lt;/h2&gt;

&lt;p&gt;Arrays are ordered lists that can store multiple values in a single variable.&lt;br&gt;&lt;br&gt;
You can think of them as containers or shelves, where each slot holds an item — like a list of enemies, levels, or collected items.&lt;/p&gt;

&lt;p&gt;Each item in an array is stored at a numbered position called an &lt;strong&gt;index&lt;/strong&gt; , starting at  &lt;strong&gt;0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt40ah9tyxcoug2y0d4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt40ah9tyxcoug2y0d4l.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Arrays Are Needed
&lt;/h3&gt;

&lt;p&gt;Arrays are essential whenever you need to handle more than one piece of related data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A list of enemies in a level&lt;/li&gt;
&lt;li&gt;All items in the player’s inventory&lt;/li&gt;
&lt;li&gt;A sequence of checkpoints or spawn points&lt;/li&gt;
&lt;li&gt;A queue of dialog lines or sound effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without arrays, you’d need a separate variable for every element (enemy1, enemy2, enemy3…), which quickly becomes unmanageable and performance heavy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;array_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;array_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;array_name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;arrayName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value3&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;arrayName&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;listName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value3&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;listName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GDScript Methods
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6dimgmkbtlkxrqlclur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6dimgmkbtlkxrqlclur.png" alt="Godot 4 Book of Code" width="800" height="997"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  C# Methods
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbm1r3sne8gw15q9gue4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbm1r3sne8gw15q9gue4.png" alt="Godot 4 Book of Code" width="800" height="1028"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use arrays for ordered data&lt;/strong&gt; where position matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access elements by index&lt;/strong&gt;  — array[0] gets the first item.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use loops&lt;/strong&gt; to efficiently process all items.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be careful with indices&lt;/strong&gt;  — trying to access an index that doesn’t exist causes an error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use methods like append(), erase(), or size()&lt;/strong&gt; to manage array contents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use arrays to handle multiple enemies.&lt;/p&gt;

&lt;p&gt;We start by defining an array named enemies, which holds a list of enemy names. Next, we print the first element in the array (at index 0), which is “Goblin”. After that, we add a new enemy “Dragon” to the list. When we print the array again, it will then display the updated list: [“Goblin”, “Orc”, “Troll”, “Dragon”]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Goblin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Orc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Troll&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Access the first element
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# Output: Goblin
# Add a new enemy
&lt;/span&gt;&lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dragon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Loop through the list
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create an array of enemies&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Goblin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Orc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Troll"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Access the first element&lt;/span&gt;
&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Output: Goblin&lt;/span&gt;
&lt;span class="c1"&gt;// Convert to a dynamic list to add new items&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemyList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;enemyList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dragon"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Loop through the list&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enemyList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw74toxdwwpatoq360602.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw74toxdwwpatoq360602.png" alt="Godot 4 Book of Code" width="800" height="65"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Dictionaries
&lt;/h2&gt;

&lt;p&gt;Dictionaries store data as key–value pairs, allowing you to label each piece of information instead of relying on numerical positions.&lt;/p&gt;

&lt;p&gt;Think of a dictionary as a filing cabinet — the key is the label on the drawer, and the value is what’s inside. This makes your data easier to understand and access, especially when order isn’t important but &lt;em&gt;meaning&lt;/em&gt; is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh19uz6rrb5ty6e3ohem2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh19uz6rrb5ty6e3ohem2.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Dictionaries Are Needed
&lt;/h3&gt;

&lt;p&gt;Dictionaries are perfect for data that needs names instead of numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storing player stats like {“health”: 100, “mana”: 50}&lt;/li&gt;
&lt;li&gt;Tracking inventory items and their quantities&lt;/li&gt;
&lt;li&gt;Keeping NPC dialog by character name&lt;/li&gt;
&lt;li&gt;Mapping key bindings or configuration settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without dictionaries, you’d need separate variables or parallel arrays for every related value — which quickly gets messy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;dict_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;dict_name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;dictName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;dictName&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"key3"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GDScript Methods
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyi3v4ogf8tjsdl2ijzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyi3v4ogf8tjsdl2ijzt.png" alt="Godot 4 Book of Code" width="800" height="879"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  C# Methods
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz6k13cwtj3gtei6cm8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz6k13cwtj3gtei6cm8n.png" alt="Godot 4 Book of Code" width="800" height="1117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use dictionaries when labels make data clearer&lt;/strong&gt;  — e.g., player["health"] is more readable than player[0].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access values by key&lt;/strong&gt; , not index — use dict["key_name"].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check for existence&lt;/strong&gt; before accessing a key to avoid errors (if “health” in player:).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use nested dictionaries&lt;/strong&gt; for structured data (like characters, stats, or items).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In C#&lt;/strong&gt; , use Dictionary for type-safe collections.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use dictionaries to store player stats and inventory.&lt;/p&gt;

&lt;p&gt;In the code below, we create a new dictionary for our players values — storing their name, health, and mana. We then add a new value to the dictionary, which will store the amount of gold that they have. Finally, we iterate over the dictionary to return the updated dictionary, which will be: {“name”: “Bob”, “health”: 100, “mana”: 50, “gold”: 250}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a dictionary of player stats
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Access a value by key
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# Output: 100
&lt;/span&gt;
&lt;span class="c1"&gt;# Add a new key-value pair
&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;

&lt;span class="c1"&gt;# Loop through keys and values
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a dictionary of player stats&lt;/span&gt;
&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"mana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Access a value by key&lt;/span&gt;
&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"health"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Output: 100&lt;/span&gt;

&lt;span class="c1"&gt;// Add a new key-value pair&lt;/span&gt;
&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"gold"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;250&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Loop through all keys and values&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgugb6gg5l16ebr7kdmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgugb6gg5l16ebr7kdmd.png" alt="Godot 4 Book of Code" width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Resources
&lt;/h2&gt;

&lt;p&gt;Resources in Godot are data objects that can be saved, loaded, and reused across your project. They’re stored as .tres (text-based) or .res (binary) files, and can contain variables, configurations, or even scripts — anything from item stats and materials to player data or configuration settings.&lt;/p&gt;

&lt;p&gt;Think of them as data containers that live outside your scripts, allowing you to manage information in a clean, modular way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Resources Are Needed
&lt;/h3&gt;

&lt;p&gt;Resources make your game more modular, reusable, and data-driven. Instead of hardcoding every item and managing a list of arrays or dictionaries, you can store that information in &lt;strong&gt;Resource files&lt;/strong&gt; and reuse them across multiple scenes or objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ll typically use Resources to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store &lt;strong&gt;item stats&lt;/strong&gt; (like damage, rarity, or price).&lt;/li&gt;
&lt;li&gt;Define &lt;strong&gt;enemy attributes&lt;/strong&gt; or &lt;strong&gt;character abilities&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create &lt;strong&gt;configuration files&lt;/strong&gt; for tuning and game balance.&lt;/li&gt;
&lt;li&gt;Create &lt;strong&gt;NPC, enemy, or character data&lt;/strong&gt; which can be loaded into scenes.&lt;/li&gt;
&lt;li&gt;Save and load &lt;strong&gt;player progress or inventory data&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Define &lt;strong&gt;materials, audio effects, shaders, and particle settings&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without resources, you’d have to duplicate data across scripts or scenes, making your project harder to update, maintain, and balance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Resource Example
&lt;/h3&gt;

&lt;p&gt;You can &lt;strong&gt;create your own resource classes&lt;/strong&gt; to store structured data, such as an RPG item database or character stats.&lt;/p&gt;

&lt;h4&gt;
  
  
  GDScript
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ItemData.gd
extends Resource
@export var name: String
@export var damage: int
@export var price: int
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you’ve created your custom Resource script (for example, &lt;a href="http://itemdata.gd/" rel="noopener noreferrer"&gt;ItemData.gd&lt;/a&gt;), you can easily create Resource files directly inside the Godot Editor — no code needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To create a Resource file:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;FileSystem&lt;/strong&gt; panel, right-click anywhere in your data/ folder (or wherever you want to store it).&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;New Resource&lt;/strong&gt; → &lt;strong&gt;Create Resource&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the window that appears, scroll down and select your custom class (e.g., ItemData).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; , then assign your script (&lt;a href="http://itemdata.gd/" rel="noopener noreferrer"&gt;ItemData.gd&lt;/a&gt;) if it’s not already linked.&lt;/li&gt;
&lt;li&gt;You’ll now see your custom exported variables (like name, damage, and price) in the &lt;strong&gt;Inspector&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Fill in their values — e.g. name = "Sword", damage = 10, price = 100.&lt;/li&gt;
&lt;li&gt;Save it as sword.tres.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdwdvqdmg8zudtji4iu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdwdvqdmg8zudtji4iu0.png" alt="Godot 4 Book of Code" width="445" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslye9uwvj5rczbtwrbsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslye9uwvj5rczbtwrbsu.png" alt="Godot 4 Book of Code" width="523" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm9r09hwpz2r4j4xh4wy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm9r09hwpz2r4j4xh4wy.png" alt="Godot 4 Book of Code" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7qefsr80zrurykct6sc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7qefsr80zrurykct6sc.png" alt="Godot 4 Book of Code" width="519" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, you could create multiple item resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data/
  sword.tres
  axe.tres
  potion.tres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then load them in-game:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var sword = load("res://data/sword.tres")
print(sword.name, "does", sword.damage, "damage")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  C
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ItemData.cs
using Godot;

[GlobalClass]
public partial class ItemData : Resource
{
    [Export] public string Name { get; set; }
    [Export] public int Damage { get; set; }
    [Export] public int Price { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now create .tres resources from this script directly in the editor — each one representing an item.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use .tres for text-based resources (readable and version control friendly).&lt;/li&gt;
&lt;li&gt;Keep reusable data in res://data/ or a similar dedicated folder.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;custom Resource scripts&lt;/strong&gt; for structured data (like items, quests, or NPCs).&lt;/li&gt;
&lt;li&gt;Don’t hardcode data — load and reference Resource files instead.&lt;/li&gt;
&lt;li&gt;Reuse Resources between multiple nodes or scenes whenever possible.&lt;/li&gt;
&lt;li&gt;Avoid circular references (when Resources reference each other in a loop).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you can create, load, and use Resources dynamically to power your game’s item system.&lt;/p&gt;

&lt;h4&gt;
  
  
  GDScript
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Game.gd
extends Node

func _ready():
    var sword = load("res://data/sword.tres")
    print("Picked up:", sword.name)
    print("Damage:", sword.damage)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  C
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Godot;

public partial class Game : Node
{
    public override void _Ready()
    {
        var sword = (ItemData)GD.Load("res://data/sword.tres");
        GD.Print($"Picked up: {sword.Name}");
        GD.Print($"Damage: {sword.Damage}");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Part IV: Gameplay Mechanics
&lt;/h1&gt;

&lt;p&gt;Now that you understand how to store data and control logic, it’s time to explore the coding features that can help make your game &lt;em&gt;interactive.&lt;/em&gt; Gameplay mechanics are what bring your project to life by connecting player actions, objects, and events in real time. They’re what make doors open, characters jump, and music change when you take damage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this section, we’ll explore:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#signals" rel="noopener noreferrer"&gt;&lt;strong&gt;Signals (Events)&lt;/strong&gt;&lt;/a&gt; — letting nodes communicate with each other&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Input&lt;/strong&gt;  &lt;/a&gt;— handling player actions and controls&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_timer.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Timers&lt;/strong&gt;  &lt;/a&gt;— triggering delayed or repeated actions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/idle_and_physics_processing.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Physics Process vs. Process&lt;/strong&gt;  &lt;/a&gt;— controlling frame updates and physics logic&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/classes/class_randomnumbergenerator.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Random Numbers&lt;/strong&gt;&lt;/a&gt; — adding unpredictability and variety&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Signals (Events)
&lt;/h2&gt;

&lt;p&gt;Signals are Godot’s way of letting nodes communicate without being directly connected. Think of them as events, where one node or part of the code “emits” a signal, and another “listens” and reacts to it. This makes your game more modular and organized, since nodes don’t need to directly reference each other to interact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpau7h1pem8tabagz1xoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpau7h1pem8tabagz1xoh.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can use signals for all sorts of gameplay interactions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notify the game that the Start button was pressed → start the game&lt;/li&gt;
&lt;li&gt;Have the UI flash red when the player takes damage&lt;/li&gt;
&lt;li&gt;When an action is pressed, tell the door to open&lt;/li&gt;
&lt;li&gt;When an animation is complete, switch to the next one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Signals turn isolated nodes into a living system that reacts to events in real time, which is a key concept for dynamic, responsive gameplay.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Signals Are Needed
&lt;/h3&gt;

&lt;p&gt;Signals allow for clean, modular communication between game elements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ll use them to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect button presses in UI&lt;/li&gt;
&lt;li&gt;React when a player’s health changes&lt;/li&gt;
&lt;li&gt;Trigger events when a collision shape is entered or exited&lt;/li&gt;
&lt;li&gt;Notify scripts when timers finish or animations end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without signals, nodes would need to constantly “poll” each other, ultimately creating messy code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;I like to think that signals are comprised of three main parts: &lt;strong&gt;Event → Listener → Response&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Emitting a signal (Event)
&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="nf"&gt;health_changed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;health_changed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Connecting a signal (Listener)
&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_on_button_pressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Defining the action (Response)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Button was pressed!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Emitting a signal (Event)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HealthChangedEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;newHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;EmitSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HealthChanged&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Connecting a signal (Listener)&lt;/span&gt;
&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pressed&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnButtonPressed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Response method (Response)&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnButtonPressed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Button was pressed!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use signals to decouple logic&lt;/strong&gt;  — nodes shouldn’t depend directly on each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect signals in&lt;/strong&gt; _ready() or in the editor for clarity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name custom signals descriptively&lt;/strong&gt; , like player_died or door_opened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disconnect unused signals&lt;/strong&gt; to prevent unexpected behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s a simple setup where pressing a button updates the player’s health bar.&lt;/p&gt;

&lt;p&gt;In the code below, we &lt;strong&gt;define a signal&lt;/strong&gt; called health_changed in the Player script. When our player takes damage, we &lt;strong&gt;emit this signal&lt;/strong&gt; to notify the other parts in our game that our health has changed.&lt;/p&gt;

&lt;p&gt;When the signal is emitted, the other parts of our code which are connected to it, should execute their logic. In this case, we have another script called UI, which &lt;strong&gt;connects to this signal&lt;/strong&gt; in the ready() function. We are connecting this signal to a new function in this script called on_health_changed. This tells the game our &lt;strong&gt;UI&lt;/strong&gt; script is &lt;strong&gt;listening for events&lt;/strong&gt; (emits) from the &lt;strong&gt;Player&lt;/strong&gt; script, and whenever that event occurs, the logic within the function will execute - which in this case is a simple print statement notifying us of our new health value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Player.gd
&lt;/span&gt;
&lt;span class="c1"&gt;# Signal creation
&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="nf"&gt;health_changed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="c1"&gt;# Signal emission (Event)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="n"&gt;health_changed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# UI.gd
&lt;/span&gt;
&lt;span class="c1"&gt;# Signal connection (Listener)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;../Player&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;health_changed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_on_health_changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Signal action (Response)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_health_changed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_health&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player health:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Player.cs&lt;/span&gt;

&lt;span class="c1"&gt;// Signal creation&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;HealthChangedEventHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;newHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Signal emission (Event)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TakeDamage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;EmitSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HealthChanged&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// UI.cs&lt;/span&gt;

&lt;span class="c1"&gt;// Signal connection (Listener)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"../Player"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"HealthChanged"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OnHealthChanged&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Signal action (Response)&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnHealthChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;newHealth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player health: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;newHealth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Input
&lt;/h2&gt;

&lt;p&gt;Input is how players interact with your game. This can be via pressing keys, clicking, or touching the screen to control characters and trigger actions. Godot’s input system makes it easy to detect and respond to player actions through code or the Input Map (found in &lt;em&gt;Project → Project Settings → Input Map&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffuc3g6iwxbabz9ypb0fn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffuc3g6iwxbabz9ypb0fn.png" alt="Godot 4 Book of Code" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can think of Input as the player’s choices, and your game listens and reacts accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Input Is Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Every interactive game depends on Input:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moving the player character&lt;/li&gt;
&lt;li&gt;Jumping, attacking, or using abilities&lt;/li&gt;
&lt;li&gt;Navigating menus or UI&lt;/li&gt;
&lt;li&gt;Detecting gamepad or touchscreen actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without Input handling, your game wouldn’t know what the player wants to do, and the player won’t have any way of interacting with the game, they would just sit idle!&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Detecting input actions continuously (we'll move right as long as we hold key)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_right&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# logic
&lt;/span&gt;
&lt;span class="c1"&gt;# Detecting input actions once-off (we'll jump once and have to press key again)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jump&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# logic
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Detecting input actions continuously (we'll move right as long as we hold key)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_right"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
       &lt;span class="c1"&gt;// logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Detecting input actions once-off (we'll jump once and have to press key again)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputEvent&lt;/span&gt; &lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jump"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="c1"&gt;// logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Input Methods
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cppw8g8de8mnup4tvox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cppw8g8de8mnup4tvox.png" alt="Godot 4 Book of Code" width="800" height="823"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use the Input Map&lt;/strong&gt; instead of hardcoding keys — this lets players rebind controls easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check for actions&lt;/strong&gt; (like "ui_accept" or "move_left") rather than specific keys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; _process() for continuous input (movement), and _input() for one-time actions (button presses).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support multiple devices&lt;/strong&gt; (keyboard, controller, touchscreen) whenever possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep input logic separate&lt;/strong&gt; from gameplay logic — use signals or dedicated functions to handle actions cleanly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s a simple movement script that lets a player move left and right, and jump when the spacebar is pressed.&lt;/p&gt;

&lt;p&gt;In the code below, the move_right and move_left keys have been assigned to the ← → keys in the &lt;strong&gt;Project Settings&lt;/strong&gt; , and the jump key to the spacebar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extpends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;JUMP_FORCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZERO&lt;/span&gt;

    &lt;span class="c1"&gt;# Move player left and right
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_right&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_left&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;

    &lt;span class="c1"&gt;# Move player up (jump)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_on_floor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_just_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jump&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JUMP_FORCE&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;200f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;JumpForce&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;400f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_PhysicsProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Vector2&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Velocity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Move player left and right&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_right"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_left"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Move player up (jump) &lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;IsOnFloor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionJustPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jump"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JumpForce&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Velocity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;MoveAndSlide&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Timers
&lt;/h2&gt;

&lt;p&gt;Timers are nodes that let you run code after a delay or repeatedly at fixed intervals. They’re essential for creating time-based events such as cooldowns, countdowns, enemy spawns, or temporary effects.&lt;/p&gt;

&lt;p&gt;Think of a timer as an alarm clock inside your game: you set it, wait, and when it rings, something happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ryr0dlczf6tplbe61k1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ryr0dlczf6tplbe61k1.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Timers Are Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Games constantly rely on timing to feel dynamic and balanced:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Countdown before starting a match&lt;/li&gt;
&lt;li&gt;Enemy attack intervals&lt;/li&gt;
&lt;li&gt;Power-up durations or cooldowns&lt;/li&gt;
&lt;li&gt;Auto-saving or periodic events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without timers, you’d need to manually track time using variables, which quickly becomes messy and unreliable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Creating and starting a timer
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="c1"&gt;# how long it will execute for (2 seconds)
&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one_shot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# will execute once, set to false for continuous execution
&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# start the timer
&lt;/span&gt;
&lt;span class="c1"&gt;# Connecting timeout signal
&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_on_timer_timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# When timer times out, do this logic
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_timer_timeout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s up!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Creating and starting a timer&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;AddChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2.0f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// how long it will execute for (2 seconds)&lt;/span&gt;
&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneShot&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// will execute once, set to false for continuous execution&lt;/span&gt;
&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// start the timer&lt;/span&gt;
&lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnTimerTimeout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;// When timer times out, do this logic&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnTimerTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Time's up!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Timer nodes&lt;/strong&gt; for clarity instead of manually counting seconds in _process().&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect the&lt;/strong&gt; timeout signal to trigger actions cleanly when the timer finishes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set&lt;/strong&gt; one_shot to true for single-use timers, or false to make them loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; start() and stop() to control timers in code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reuse timers&lt;/strong&gt; for repeating events rather than creating new ones each time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use a Timer to respawn an enemy 3 seconds after it’s defeated.&lt;/p&gt;

&lt;p&gt;In the code below, we &lt;strong&gt;create a timer&lt;/strong&gt; as soon as our game starts. When it’s created, we also &lt;strong&gt;connect its timeout&lt;/strong&gt; signal to our script (this can be done in the editor itself, instead of via code). When the enemy is defeated, say their health reaches below zero, we &lt;strong&gt;start the timer&lt;/strong&gt;. The timer will run for however long we’ve set its wait_time, which is 3 seconds. When 3 seconds have passed, the &lt;strong&gt;timer will timeout&lt;/strong&gt; , and the enemy will be respawned.&lt;/p&gt;

&lt;p&gt;If the enemy dies again, the logic will start over again, unless we’ve set our timer to be one_shot enabled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="c1"&gt;# Create timer
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;respawn_timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;RespawnTimer&lt;/span&gt;
    &lt;span class="n"&gt;respawn_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt; 
    &lt;span class="n"&gt;respawn_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one_shot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;respawn_timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_on_respawn_timer_timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Start timer
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;on_enemy_defeated&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemy defeated! Respawning in 3 seconds...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;RespawnTimer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Stop timer
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_respawn_timer_timeout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemy has respawned!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EnemySpawner&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create timer&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Timer&lt;/span&gt; &lt;span class="n"&gt;RespawnTimer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;RespawnTimer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"RespawnTimer"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;RespawnTimer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitTime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;0f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;RespawnTimer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneShot&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    
        &lt;span class="n"&gt;RespawnTimer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnRespawnTimerTimeout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Start timer&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnEnemyDefeated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enemy defeated! Respawning in 3 seconds..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;RespawnTimer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Stop timer&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnRespawnTimerTimeout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enemy has respawned!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Physics Process vs. Process
&lt;/h2&gt;

&lt;p&gt;In Godot, both _process() and _physics_process() are special built-in functions that run every frame — but they serve different purposes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;_process(delta) runs &lt;em&gt;every rendered frame&lt;/em&gt; — perfect for animations, UI, and non-physics logic.&lt;/li&gt;
&lt;li&gt;_physics_process(delta) runs &lt;em&gt;at a fixed time step&lt;/em&gt; — perfect for movement, collisions, and anything that interacts with the physics engine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs27vwjix8zm0sc9fgb2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs27vwjix8zm0sc9fgb2j.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why It Matters
&lt;/h3&gt;

&lt;p&gt;Games depend on predictable, consistent updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ll typically use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;_process() → for animations, timers, and UI transitions.&lt;/li&gt;
&lt;li&gt;_physics_process() → for movement, gravity, and collisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Called every frame (variable time step)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# do framerate related logic
&lt;/span&gt;
&lt;span class="c1"&gt;# Called at a fixed time step (default: 60 times per second)
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# do physics related logic
&lt;/span&gt;    &lt;span class="c1"&gt;# usually ends in move_and_slide() or move_and_collide()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Called every frame&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// do framerate related logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Called at a fixed physics tick rate&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_PhysicsProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do physics related logic&lt;/span&gt;
    &lt;span class="c1"&gt;// usually ends in MoveAndSlide() or MoveAndCollide()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; _physics_process() for movement and collisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; _process() for visual effects and non-physics updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always multiply by&lt;/strong&gt; delta to keep movement frame-rate independent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t mix physics logic in&lt;/strong&gt; _process() — it can cause jitter or inconsistencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pause logic carefully&lt;/strong&gt;  — timers and physics might still run if not managed properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s a basic player script that plays a characters &lt;strong&gt;run animations continuously&lt;/strong&gt; whilst the input keys are being held down in the process() function. It also then &lt;strong&gt;moves the character around&lt;/strong&gt; whilst the input keys are being held down in the physics_process() function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This will play the run animations on inputs
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_right&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_left&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;idle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# This will move the player on inputs.
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZERO&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_right&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;move_left&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;200f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"AnimatedSprite2D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// This will play the run animations on inputs&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_left"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// This will move the player on inputs.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_PhysicsProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Vector2&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_right"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"move_left"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Velocity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;MoveAndSlide&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Random Numbers
&lt;/h2&gt;

&lt;p&gt;Random numbers add variety and unpredictability to your game, thus ensuring no two playthroughs feel exactly the same. Godot’s random system lets you generate numbers, select random items from arrays, or even produce random directions for projectiles or enemies.&lt;/p&gt;

&lt;p&gt;Randomness makes things feel dynamic, alive, and surprising.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Random Numbers Are Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Games rely on randomness for endless replayability:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loot drops or item rewards&lt;/li&gt;
&lt;li&gt;Random enemy spawns&lt;/li&gt;
&lt;li&gt;Critical hits or damage variation&lt;/li&gt;
&lt;li&gt;Procedural generation (maps, terrain, puzzles)&lt;/li&gt;
&lt;li&gt;Particle spread or visual effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without randomness, your game would feel repetitive and predictable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Initialize random seed (usually in _ready)
&lt;/span&gt;&lt;span class="nf"&gt;randomize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Generate a random float between 0 and 1
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;randf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Generate an integer between 0 and 10
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;randi_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Pick a random element from an array
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Goblin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Orc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Troll&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;random_enemy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pick_random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Random vector direction
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;randf_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;randf_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RandomExample&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Random float between 0 and 1&lt;/span&gt;
        &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NextDouble&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Random integer between 0 and 10&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Random element from an array&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Goblin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Orc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Troll"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;randomEnemy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;

        &lt;span class="c1"&gt;// Random direction&lt;/span&gt;
        &lt;span class="n"&gt;Vector2&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NextDouble&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NextDouble&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Normalized&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Enemy: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;randomEnemy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Direction: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; randomize() once at startup (in _ready()) to avoid repeating patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose the right random function&lt;/strong&gt;  — Godot offers several for different data types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use seeded randomness&lt;/strong&gt; for predictable results (great for replays or testing).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clamp or round values&lt;/strong&gt; if you only need whole numbers or limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep randomness balanced&lt;/strong&gt;  — too much can frustrate players.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you might use randomness to spawn enemies at random positions on the map.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;randomize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemy_scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://Enemy.tscn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;enemy_scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;randi_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nf"&gt;randi_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy_scene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Spawner&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemyScene&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PackedScene&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://Enemy.tscn"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Instantiate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;enemyScene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;801&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;AddChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemyScene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9yokzd74bb727h4ng9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9yokzd74bb727h4ng9n.png" alt="Godot 4 Book of Code" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. The Ready Function
&lt;/h2&gt;

&lt;p&gt;In Godot, the _ready() function is called &lt;strong&gt;once&lt;/strong&gt; when a node enters the scene tree and is fully initialized. It’s the go-to place for setup logic such as loading resources, connecting signals, setting initial values, or caching references to other nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Its Needed
&lt;/h3&gt;

&lt;p&gt;When a node is created, not all of its children or dependencies exist yet. If you try to reference them too early, your code can break.&lt;/p&gt;

&lt;p&gt;_ready() ensures the entire node hierarchy is loaded before running your setup code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ll typically use it to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get references to child nodes&lt;/li&gt;
&lt;li&gt;Connect signals between nodes&lt;/li&gt;
&lt;li&gt;Load textures, sounds, or scenes&lt;/li&gt;
&lt;li&gt;Initialize variables or game states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without _ready(), you’d risk calling nodes or data that don’t exist yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Called once when the node enters the scene tree
&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Set values to be initialized
&lt;/span&gt;    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;Sprite2D&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Set values to be initialized&lt;/span&gt;
        &lt;span class="n"&gt;Sprite2D&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Sprite2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sprite2D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;playerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; _ready() for one-time setup only — not for logic that runs continuously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep it clean and short&lt;/strong&gt;  — just initialization, no heavy loops or updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access child nodes here safely&lt;/strong&gt;  — all children are guaranteed to exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect signals or timers in&lt;/strong&gt; _ready(), not in _process().&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid creating dependencies between unrelated nodes&lt;/strong&gt;  — keep setups modular.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s a simple player setup that uses _ready() to load assets, connect signals, and initialize variables before gameplay starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;idle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;HealthBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt;
    &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;Area2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body_entered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_on_body_entered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_body_entered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Collided with:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;ProgressBar&lt;/span&gt; &lt;span class="n"&gt;healthBar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Area2D&lt;/span&gt; &lt;span class="n"&gt;hitArea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"AnimatedSprite2D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;healthBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MaxValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;hitArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BodyEntered&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnBodyEntered&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnBodyEntered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Collided with: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Part V: Scenes &amp;amp; Nodes
&lt;/h1&gt;

&lt;p&gt;In Godot, everything is a node. From your player and camera to UI buttons, lights, and audio — every piece of your game inherits from the Node class.&lt;/p&gt;

&lt;p&gt;Nodes are the building blocks of Godot. When you combine them, you create scenes, which are self-contained groups of nodes that can represent anything: a level, a character, or even a menu. Together, these form the Scene Tree, a hierarchy that defines how everything in your game is organized, updated, and connected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this section, we’ll cover:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/getting_started/step_by_step/nodes_and_scenes.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Node Basics&lt;/strong&gt;&lt;/a&gt; — understanding what nodes are and how they work&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/getting_started/step_by_step/nodes_and_scenes.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Scenes&lt;/strong&gt;  &lt;/a&gt;— reusable groups of nodes that form your game’s structure&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#inheritance" rel="noopener noreferrer"&gt;&lt;strong&gt;Inheritance&lt;/strong&gt;  &lt;/a&gt;— allows one scene or script to reuse another’s logic and structure.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_exports.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Export variables&lt;/strong&gt;&lt;/a&gt; — makes a variable visible and editable in the Inspector panel.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/groups.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Groups &lt;/strong&gt;&lt;/a&gt;— tagging nodes into similar categories&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Accessing Nodes
&lt;/h2&gt;

&lt;p&gt;A Node is the most fundamental building block in Godot. Each node has a name, a type, and optional children. Nodes within a scene creates a tree-like structure that defines how your game world is built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it like this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Nodes&lt;/em&gt; are the building blocks.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Scenes&lt;/em&gt; are the containers which hold and organize nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a more visual reference on all the nodes and their use-cases, refer to my &lt;a href="https://app.gitbook.com/o/cPjnkDazMpEboptvVAgZ/s/2Aq0MNHhA8LaPrbZ2ewE/~/changes/130/free-resources/godot-book-of-nodes" rel="noopener noreferrer"&gt;&lt;strong&gt;Book of Nodes&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpoi7tcbxa26ly3c36093.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpoi7tcbxa26ly3c36093.png" alt="Godot 4 Book of Code" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;View the online version of the above depiction of scenes and nodes &lt;a href="https://app.mural.co/t/godot5664/m/godot5664/1680196108691/c8c74015cd7e5090492ac132dd78a64656af7fcc?sender=u55125f0ffcb42f94c9c58346" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Nodes Are Needed
&lt;/h3&gt;

&lt;p&gt;Without nodes, there would be no game. They’re the foundation of everything you create in Godot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nodes can represent almost anything:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A collider that detects hits&lt;/li&gt;
&lt;li&gt;A sprite that displays a texture&lt;/li&gt;
&lt;li&gt;A camera that follows the player&lt;/li&gt;
&lt;li&gt;A light that illuminates the scene&lt;/li&gt;
&lt;li&gt;A script that controls behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without nodes, every part of your game would have to be hard-coded, messy, unorganized, and nearly impossible to maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;Nodes are usually added within the editor itself, but we can create and reference nodes directly within our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Referencing an existing node and changing its property 
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;Sprite2D&lt;/span&gt;
&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modulate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RED&lt;/span&gt;

&lt;span class="c1"&gt;# Getting a node by path
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Camera2D&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Creating a new node
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;new_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;new_label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Referencing an existing node and changing its property &lt;/span&gt;
&lt;span class="n"&gt;Sprite2D&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Sprite2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sprite2D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Modulate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Getting a node by path&lt;/span&gt;
&lt;span class="n"&gt;Camera2D&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Camera2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Camera2D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Creating a new node&lt;/span&gt;
&lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="n"&gt;newLabel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;newLabel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;AddChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newLabel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name nodes clearly&lt;/strong&gt; (e.g., PlayerSprite, Hitbox, MainCamera).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use composition&lt;/strong&gt;  — build functionality by combining nodes, not writing giant scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage node types&lt;/strong&gt;  — use the right node for the job (Area2D for detection, Sprite2D for visuals, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the tree organized&lt;/strong&gt;  — indentation and naming go a long way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t overload one scene&lt;/strong&gt;  — break your game into multiple smaller, reusable ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you can reference a node that already exists &lt;strong&gt;and&lt;/strong&gt; create a new one dynamically in the same script.&lt;/p&gt;

&lt;p&gt;In the code below, we assume that within the editor we’ve added a &lt;strong&gt;Sprite2D&lt;/strong&gt; node called “Sprite2D”. We reference this node in our script, and then we change its texture (sprite). We also create a new &lt;strong&gt;Label&lt;/strong&gt; node with the text “Player ready”, and position it to our screen. The add_child() method adds the newly created node to our scene via the script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Reference an existing Sprite node
&lt;/span&gt;    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;Sprite2D&lt;/span&gt;
    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://sprites/player.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create and add a new Label node
&lt;/span&gt;    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player ready!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Reference an existing node&lt;/span&gt;
        &lt;span class="n"&gt;Sprite2D&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Sprite2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sprite2D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Texture&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Texture2D&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://sprites/player.png"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Create and add a new node dynamically&lt;/span&gt;
        &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Player ready!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;AddChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2wbiyczg52ifb2kjqja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2wbiyczg52ifb2kjqja.png" alt="Godot 4 Book of Code" width="800" height="70"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Accessing Scenes
&lt;/h2&gt;

&lt;p&gt;A Scene in Godot is a collection of nodes. It can represent this such as a character, a level, a user interface, or even a single reusable object.&lt;/p&gt;

&lt;p&gt;Every scene has a &lt;strong&gt;root node&lt;/strong&gt; , and that root defines the scene’s type. For example, a CharacterBody2D might be the root for a player scene, or a Control node might be the root for a UI screen.&lt;/p&gt;

&lt;p&gt;Think of scenes as blueprints: you build them once in the editor, then reuse, instance, or switch between them dynamically during gameplay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctxd2js6zhajzlk705mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctxd2js6zhajzlk705mj.png" alt="Godot 4 Book of Code" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;View the online version of the above depiction of scenes and nodes &lt;a href="https://app.mural.co/t/godot5664/m/godot5664/1680196108691/c8c74015cd7e5090492ac132dd78a64656af7fcc?sender=u55125f0ffcb42f94c9c58346" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Scenes Are Needed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenes make your game modular and reusable. They allow you to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build individual pieces of your game separately.&lt;/li&gt;
&lt;li&gt;Reuse the same object (like enemies or items) multiple times.&lt;/li&gt;
&lt;li&gt;Load and unload levels dynamically.&lt;/li&gt;
&lt;li&gt;Transition between menus, gameplay, and cutscenes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without scenes, your entire game would live in one massive, unmanageable hierarchy, which makes updates, debugging, and testing a nightmare.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Load a scene from file
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemy_scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://scenes/Enemy.tscn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create an instance of that scene
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemy_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enemy_scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Add it to the current scene tree
&lt;/span&gt;&lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy_instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Change to another scene file
&lt;/span&gt;&lt;span class="nf"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;change_scene_to_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://scenes/Level2.tscn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Reload the current scene
&lt;/span&gt;&lt;span class="nf"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;reload_current_scene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Get a node from another scene (if it's loaded)
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_root&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World/Player&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Load a scene from file&lt;/span&gt;
&lt;span class="n"&gt;PackedScene&lt;/span&gt; &lt;span class="n"&gt;enemyScene&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PackedScene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://scenes/Enemy.tscn"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create an instance of that scene&lt;/span&gt;
&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="n"&gt;enemyInstance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enemyScene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Instantiate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Add it to the current scene tree&lt;/span&gt;
&lt;span class="nf"&gt;AddChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemyInstance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Change to another scene file&lt;/span&gt;
&lt;span class="nf"&gt;GetTree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ChangeSceneToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://scenes/Level2.tscn"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Reload the current scene&lt;/span&gt;
&lt;span class="nf"&gt;GetTree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ReloadCurrentScene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Get a node from another scene (if it's loaded)&lt;/span&gt;
&lt;span class="n"&gt;Node&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetTree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"World/Player"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep scenes focused&lt;/strong&gt;  — each should represent one clear purpose (e.g., Player, MainMenu, Enemy, Level1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the root node type wisely&lt;/strong&gt;  — it defines what the scene &lt;em&gt;is&lt;/em&gt; and how it behaves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance scenes instead of duplicating&lt;/strong&gt;  — this makes updates propagate automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; get_tree().change_scene_to_file() for transitions, and preload() or load() for instancing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep references clean&lt;/strong&gt;  — don’t rely on global paths unless necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;The below code &lt;strong&gt;loads and spawns&lt;/strong&gt; an enemy scene when the player presses a key, and &lt;strong&gt;transitions&lt;/strong&gt; to a new scene when health reaches zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="c1"&gt;# Load scene
&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemy_scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://scenes/Enemy.tscn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Spawn enemy when pressing "E"
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_just_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spawn_enemy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enemy_scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# Spawn scene
&lt;/span&gt;        &lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Change to game over scene when health reaches zero
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;get_tree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;change_scene_to_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://scenes/GameOver.tscn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Transition scene
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Level&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Load scene&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;PackedScene&lt;/span&gt; &lt;span class="n"&gt;enemyScene&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PackedScene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://scenes/Enemy.tscn"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsActionJustPressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spawn_enemy"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Node2D&lt;/span&gt; &lt;span class="n"&gt;enemy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;enemyScene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instantiate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Node2D&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Spawn scene&lt;/span&gt;
            &lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;AddChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enemy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;GetTree&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ChangeSceneToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://scenes/GameOver.tscn"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Transition scene&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Inheritance
&lt;/h2&gt;

&lt;p&gt;Inheritance allows you to create new scenes or scripts that reuse and extend the functionality of existing ones. It’s one of the most powerful features of coding, as it lets you define a base behavior (like a generic “Enemy”) and then build specialized versions (like “Goblin” or “Orc”) without rewriting everything from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are two main types of inheritance in Godot:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Script inheritance&lt;/strong&gt;  — extending another script’s code using the extends keyword.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scene inheritance&lt;/strong&gt;  — creating new scenes that build on existing ones in the editor.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why Inheritance Is Needed
&lt;/h3&gt;

&lt;p&gt;Inheritance helps you write cleaner, reusable, and modular code. It keeps your project organized and avoids duplication when many objects share similar traits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A base Enemy scene might define health and damage logic for all enemies.&lt;/li&gt;
&lt;li&gt;Derived scenes like Orc, Goblin, or Troll can inherit that and add their own unique animations or stats.&lt;/li&gt;
&lt;li&gt;A CharacterBody2D script might define general movement for all characters in your game, and the Player script can extend it to handle input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without inheritance, you’d have to duplicate large chunks of code or rebuild scenes from scratch every time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztz2hi5288tefqntaoab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztz2hi5288tefqntaoab.png" alt="Godot 4 Book of Code" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use inheritance for shared functionality&lt;/strong&gt; , not for one-off behaviors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep base classes simple and focused&lt;/strong&gt;  — they should define core rules, not everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Override functions responsibly&lt;/strong&gt;  — always call super() or ._process(delta) if you still want the parent’s logic to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For scenes&lt;/strong&gt; , use “Inherit Scene” in the editor instead of duplicating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use composition&lt;/strong&gt; (adding child nodes) alongside inheritance for flexibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Script Inheritance
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Base script: Base.gd
# The base class defines the basic values of your enemies
&lt;/span&gt;&lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemy took&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;damage. Health:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Derived script: Derived.gd
# The derived class gets everythign from the Base, such as health and take_damage() function
&lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Goblin ready!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Base script: Base.cs&lt;/span&gt;
&lt;span class="c1"&gt;// The base class defines the basic values of your enemies&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Health&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TakeDamage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Health&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Enemy took &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; damage. Health: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Derived script: Derived.cs&lt;/span&gt;
&lt;span class="c1"&gt;// The derived class gets everythign from the Base, such as health and take_damage() function&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Derived&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Goblin ready!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TakeDamage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Scene Inheritance
&lt;/h4&gt;

&lt;p&gt;You can also inherit scenes directly in the editor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click an existing scene (e.g., Enemy.tscn).&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;“New Inherited Scene”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Godot creates a new version with all the parent nodes — ready for customization.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib364zt6h0yu5pknle6l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib364zt6h0yu5pknle6l.png" alt="Godot 4 Book of Code" width="619" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can then:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add new child nodes (e.g., a weapon or animation).&lt;/li&gt;
&lt;li&gt;Override properties (like textures, speeds, or collision shapes).&lt;/li&gt;
&lt;li&gt;Change script references while keeping base functionality intact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;The code below creates a &lt;strong&gt;base&lt;/strong&gt;  &lt;strong&gt;Enemy class&lt;/strong&gt; , which defines the &lt;strong&gt;shared behavior&lt;/strong&gt; for all of our enemies. We then create &lt;strong&gt;two derived classes&lt;/strong&gt; (Orc and Troll) which extends from it. These classes will get all the base functionality, such as health and take_damage(), but will still be able to get their own unique features.&lt;/p&gt;

&lt;p&gt;This means our damage logic is the same for all enemies, but different enemies can have different animations, sound, and behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Base Enemy.gd
&lt;/span&gt;&lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="n"&gt;Enemy&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemy spawned with&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemy took damage:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Orc.gd (inherits Enemy.gd)
# Orc plays a dance anim on taking damage, whilst still losing health
&lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Enemy&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Orc enters the battlefield!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Orc roars in anger!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;animated_sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dance_anim&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Troll.gd (inherits Enemy.gd)
&lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res://scripts/Enemy.gd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Troll regenerates some health!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Export Variables
&lt;/h2&gt;

&lt;p&gt;Export variables let you expose script properties directly to the Godot Editor. They make your scripts customizable, flexible, and designer-friendly, allowing you to change values without modifying the code.&lt;/p&gt;

&lt;p&gt;Think of them as editable parameters which appear in the Inspector just like any built-in node property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ynsqa055qvd1qmcjh4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ynsqa055qvd1qmcjh4z.png" alt="Godot 4 Book of Code" width="679" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Export Variables Are Needed
&lt;/h3&gt;

&lt;p&gt;Export variables bridge the gap between code and design. Instead of opening scripts to adjust things like player speed or enemy health for testing, you can edit them visually in the editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ll typically use them for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Character attributes (health, speed, jump power)&lt;/li&gt;
&lt;li&gt;Enemy AI settings (vision range, attack delay)&lt;/li&gt;
&lt;li&gt;Visual tuning (colors, scale, offsets)&lt;/li&gt;
&lt;li&gt;Audio or effect configuration&lt;/li&gt;
&lt;li&gt;Linking external resources (textures, scenes, sounds)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without exports, tuning gameplay would mean constant code edits and reloads, which slows development dramatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# A variable visible and editable in the editor
&lt;/span&gt;&lt;span class="nd"&gt;@export&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;span class="nd"&gt;@export&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# Choose a texture in the editor
&lt;/span&gt;&lt;span class="nd"&gt;@export&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Texture2D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;200f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;PlayerName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hero"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Texture2D&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use clear names&lt;/strong&gt;  — make sure exports describe what they control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set sensible defaults&lt;/strong&gt;  — keep values playable right away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add type hints&lt;/strong&gt; (int, float, Color, PackedScene) for editor validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use ranges and enums&lt;/strong&gt; to restrict inputs and avoid mistakes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep export usage simple&lt;/strong&gt;  — avoid exporting everything just for convenience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;The below script exports variables which will be exposed to the Inspector panel for editing. This means whatever value we assign in the inspector panel will be the value assigned to that script — meaning it will overwrite hard-coded values in our script!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="nd"&gt;@export&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;200.0&lt;/span&gt;
&lt;span class="nd"&gt;@export&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;jump_force&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;400.0&lt;/span&gt;
&lt;span class="nd"&gt;@export&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite_texture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Texture2D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;200f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;JumpForce&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;400f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Texture2D&lt;/span&gt; &lt;span class="n"&gt;SpriteTexture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Groups
&lt;/h2&gt;

&lt;p&gt;Groups are a powerful way to organize and manage multiple nodes in Godot. They let you categorize nodes under a shared label (like “Enemies” or “Interactables”) so you can call functions, apply effects, or send signals to all of them at once.&lt;/p&gt;

&lt;p&gt;Think of groups as tags for nodes. You can assign one or more groups to a node and then access them from anywhere in your game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik3osrxn4oz1fdou3tms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fik3osrxn4oz1fdou3tms.png" alt="Godot 4 Book of Code" width="685" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Groups Are Needed
&lt;/h3&gt;

&lt;p&gt;Groups are essential when you have multiple instances of similar objects, like enemies, NPCs, or projectiles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ll typically use them to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply damage or effects to every enemy.&lt;/li&gt;
&lt;li&gt;Check interactions dynamically — for example, showing an “Interact” prompt when focusing on an interactable group item, or triggering dialog when focusing on an NPC.&lt;/li&gt;
&lt;li&gt;Enable or disable all interactables at once (e.g., pausing player input or freezing AI).&lt;/li&gt;
&lt;li&gt;Trigger multiple lights, doors, or sounds with a single command.&lt;/li&gt;
&lt;li&gt;Broadcast global events, like GameOver, LevelCleared, or Pause&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without groups, you’d need to manually loop through every node or keep separate arrays, which is messy, slow, and error-prone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;You can assign nodes directly to Groups within the editor, but below is how you can add objects to groups using code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add the node to a group
&lt;/span&gt;&lt;span class="nf"&gt;add_to_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check if the node belongs to a group
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_in_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This node is an enemy!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Remove the node from a group
&lt;/span&gt;&lt;span class="nf"&gt;remove_from_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enemies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add the node to a group&lt;/span&gt;
&lt;span class="nf"&gt;AddToGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enemies"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Check if the node belongs to a group&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;IsInGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enemies"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This node is an enemy!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Remove the node from a group&lt;/span&gt;
&lt;span class="nf"&gt;RemoveFromGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enemies"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use groups to organize related nodes&lt;/strong&gt; (e.g., “Enemies”, “Collectibles”, “UI”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add groups via code or the editor&lt;/strong&gt; (under the “Node → Groups” tab).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid too many overlapping groups&lt;/strong&gt;  — keep naming meaningful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; is_in_group() to check membership before applying logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage signals and&lt;/strong&gt; call_group() for clean global communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you can use groups to detect whether the player is focusing on an &lt;strong&gt;interactable object&lt;/strong&gt; (like an item, door, or NPC). If the object is in the Interactable group, the player receives a message prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Player.gd
&lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Cast a ray forward to detect what the player is looking at
&lt;/span&gt;    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;space_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_world_2d&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;direct_space_state&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;space_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersect_ray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;global_position&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Get the collider of the object
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;collider&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collider&lt;/span&gt;

        &lt;span class="c1"&gt;# If its in interactable group, show prompt
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_in_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Interactable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re focusing on an interactable. Press [E] to pick up.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re looking at:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Player.cs&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Cast a ray forward to detect what the player is looking at&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;spaceState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetWorld2D&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;DirectSpaceState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spaceState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IntersectRay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GlobalPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GlobalPosition&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the collider of the object&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"collider"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"collider"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;// If its in interactable group, show prompt&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsInGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Interactable"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You're focusing on an interactable. Press [E] to pick up."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
                &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"You're looking at: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Part VI: Bonus
&lt;/h1&gt;

&lt;p&gt;You’ve learned how to build the core gameplay systems of a Godot project. Now it’s time to focus on the &lt;em&gt;finishing touches&lt;/em&gt; that make your project clean, stable, and scalable.&lt;/p&gt;

&lt;p&gt;This section covers the tools and habits that keep your code readable, debuggable, and organized — especially as your project grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We’ll go over:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Code Style Tips&lt;/strong&gt;&lt;/a&gt; — write clear, consistent, and maintainable code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/stable/tutorials/scripting/debug/overview_of_debugging_tools.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Debugging&lt;/strong&gt;  &lt;/a&gt;— identify and fix issues effectively.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.godotengine.org/en/latest/tutorials/scripting/singletons_autoload.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Autoloads (Singletons)&lt;/strong&gt; &lt;/a&gt;— manage global data and cross-scene communication.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Code Style Tips
&lt;/h2&gt;

&lt;p&gt;Clean code isn’t just about getting things to work, it’s about making your future self thank you later.&lt;br&gt;&lt;br&gt;
Readable scripts are easier to debug, share, and extend.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why It Matters
&lt;/h3&gt;

&lt;p&gt;As projects grow, consistency becomes critical. Having clear naming, structure, and commenting habits keeps your code easy to understand for everyone (including you, months later).&lt;/p&gt;
&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use consistent naming:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;GDScript → snake_case for variables and functions.&lt;/li&gt;
&lt;li&gt;C# → camelCase for variables and PascalCase for methods and classes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comment with purpose:&lt;/strong&gt; Explain &lt;em&gt;why&lt;/em&gt;, not just &lt;em&gt;what&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group related code:&lt;/strong&gt; Keep setup, logic, and cleanup organized in sections OR code regions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid magic numbers:&lt;/strong&gt; Use constants or exported variables instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep functions short:&lt;/strong&gt; Each function should do one clear thing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be descriptive:&lt;/strong&gt; player_health is better than hp1.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Example (GDScript)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Bad
var s = 10
func x():
    s -= 1
    if s == 0: print("Dead")

func phello():
    print("Hello")

# Good
#region [Player Health Management]
var player_health = 10

func take_damage(amount):
    player_health -= amount
    if player_health &amp;lt;= 0:
        print("Player defeated")
        # Trigger game over sequence
#endregion

#region [Debugging]
func print_hello():
    print("Hello")
#endregion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Debugging
&lt;/h2&gt;

&lt;p&gt;Every developer runs into bugs, it’s just inevitable. The key is finding and understanding them quickly. Godot provides a range of built-in tools to help you diagnose problems effectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkdxie8oe2uzxa0uhc2ur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkdxie8oe2uzxa0uhc2ur.png" alt="Godot 4 Book of Code" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; print() or GD.Print() to log key values and track execution flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use&lt;/strong&gt; assert(condition) to catch unexpected states early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the Debugger panel&lt;/strong&gt; (bottom dock) to pause on errors and inspect variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage breakpoints&lt;/strong&gt; to step through your code line by line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable “Visible Collision Shapes”&lt;/strong&gt; in the Debug menu to check collisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t ignore warnings&lt;/strong&gt;  — they often point to subtle bugs before they crash your game.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player reference missing!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Player is dead&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_PhysicsProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Player reference missing!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Player is dead"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhuihsrx0hhcrhp66sqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhuihsrx0hhcrhp66sqc.png" alt="Godot 4 Book of Code" width="800" height="70"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Using Autoloads (Singletons)
&lt;/h2&gt;

&lt;p&gt;Autoloads (also called Singletons) are special scripts that stay loaded across all scenes. They’re perfect for storing global data, such as player stats, game state, settings, or audio managers.&lt;/p&gt;

&lt;p&gt;Once registered, they’re available from &lt;strong&gt;anywhere&lt;/strong&gt; in your game using their name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Autoloads Are Needed
&lt;/h3&gt;

&lt;p&gt;Autoloads make it easy to share data between scenes without constantly passing references around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They’re great for things like:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saving and loading game progress.&lt;/li&gt;
&lt;li&gt;Keeping player stats between levels.&lt;/li&gt;
&lt;li&gt;Handling global input or settings.&lt;/li&gt;
&lt;li&gt;Managing background music, pause menus, or transitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;They’re not great for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared or per-instance values, like enemy health or temporary item states. If you store shared data such as enemy health in an autoload, then when one enemy dies, &lt;em&gt;all&lt;/em&gt; others will die too.&lt;/li&gt;
&lt;li&gt;Objects that exist multiple times in the world, such as bullets, items, or NPCs.&lt;/li&gt;
&lt;li&gt;Autoloads are global, meaning every scene accesses the same data. Using them for per-object logic can cause synchronization issues or unexpected behavior between instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a new script, e.g. Global.gd.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Project → Project Settings → Autoload&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add your script and give it a name (e.g., Global).&lt;/li&gt;
&lt;li&gt;Enable “Singleton.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can access it anywhere using that name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqvwyx8yefdhpr1t3d0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqvwyx8yefdhpr1t3d0w.png" alt="Godot 4 Book of Code" width="800" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntax
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GDScript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GameManager.gd (autoload)
&lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player_health&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;coins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;add_coin&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;coins&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# Access the autoload directly from any other script
&lt;/span&gt;&lt;span class="n"&gt;GameManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_coin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coins&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C#:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GameManager.cs (autoload)&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Godot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GameManager&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;PlayerHealth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Coins&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddCoin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Coins&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Access the autoload directly from any other script&lt;/span&gt;
&lt;span class="n"&gt;GameManager&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameManager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"res://GameManager.cs"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCoin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Coins&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldse6aoodi7fcekb2dfu.png" alt="Godot 4 Book of Code" width="800" height="94"&gt;
&lt;/h2&gt;

</description>
      <category>fundamentals</category>
      <category>godot</category>
      <category>programming</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>I Made A Plugin To Update Godot From Within The Editor</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Wed, 21 Aug 2024 14:31:12 +0000</pubDate>
      <link>https://forem.com/christinec_dev/i-made-a-plugin-to-update-godot-from-within-the-editor-3g8o</link>
      <guid>https://forem.com/christinec_dev/i-made-a-plugin-to-update-godot-from-within-the-editor-3g8o</guid>
      <description>&lt;p&gt;I understand the struggle of not having the Steam version of Godot that auto-updates. If you’re like me, you might have been manually updating Godot via the website. This involves downloading the new stable version, extracting it, and then opening it. This &lt;em&gt;tedious&lt;/em&gt; process has caused me to stick with older versions of Godot for much longer than I’d like to admit. As a result, I’m always late to enjoy the latest updates and features — which in the fast-paced world of game dev, is stressful.&lt;/p&gt;

&lt;p&gt;For example, I didn’t download Godot version 4.2 until &lt;strong&gt;three months&lt;/strong&gt; after its release because I was too lazy to visit the website and update it. This isn’t the first time I’ve done this. Even now, I haven’t updated my engine to Godot 4.3, which was released a week ago.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F400%2F0%2AdA5M4ZD_09qqpr5Y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F400%2F0%2AdA5M4ZD_09qqpr5Y.gif" alt="Godot Version Update" width="400" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, how can I fix this issue? Well, as a developer, I believe in working smarter — not harder. Instead of just manually updating by navigating to the website and clicking a button, I decided to invest hours of blood, sweat, and tears to create a plugin to automate this process. Easy, peasy.&lt;/p&gt;

&lt;p&gt;And so my plugin was created. I’d like to share it with you, so you can update Godot within my editor and stay current with the latest version features. Okay, so let’s finally get rid of my ancient version of Godot and upgrade to Godot version 4.3.&lt;/p&gt;

&lt;p&gt;Let’s start by opening up a blank project, and importing and activating my Plugin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F218%2F1%2Am5az577kcPtujaxdKjgVXA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F218%2F1%2Am5az577kcPtujaxdKjgVXA.png" alt="Godot Version Update" width="218" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEWDQ9eGkjzEBa9VXnslXFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEWDQ9eGkjzEBa9VXnslXFw.png" alt="Godot Version Update" width="800" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If activated and installed correctly, there should be a new workspace available at the top called “Godot Version Updater”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9z_f1CRqeon0usgi4nznXA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9z_f1CRqeon0usgi4nznXA.png" alt="Godot Version Update" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, this workspace is made out of four parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;directory&lt;/strong&gt; selector (where you want to save your engine);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AD4kyqgXzMH40ouaMWeTF-w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AD4kyqgXzMH40ouaMWeTF-w.png" alt="Godot Version Update" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;console&lt;/strong&gt; (to show you what’s happening);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AksPbCC1k-R68ny9QhWa2Yg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AksPbCC1k-R68ny9QhWa2Yg.png" alt="Godot Version Update" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A panel showing &lt;strong&gt;version information&lt;/strong&gt; (current, latest, and an option to enable .NET support);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKdcb3J_UT0its_9jnhWmLQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKdcb3J_UT0its_9jnhWmLQ.png" alt="Godot Version Update" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;button&lt;/strong&gt; to install the latest update.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAqNGfEbjv_9azu2HKyhWNQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAqNGfEbjv_9azu2HKyhWNQ.png" alt="Godot Version Update" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, the plugin will download the latest version to your /Downloads folder. If you want to change this directory, click on the “NEW DIRECTORY” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0gkzo_RaQKUV-aKBfSXQPA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0gkzo_RaQKUV-aKBfSXQPA.png" alt="Godot Version Update" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are using Godot and GDScript, leave the “.NET Support Enabled” checkbox unchecked. If you are using Godot and C#, check this button so that it can install the .NET binaries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADW2fOhi0B9XoRnPUv7Y3cQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADW2fOhi0B9XoRnPUv7Y3cQ.png" alt="Godot Version Update" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you’re ready, click the download button. You will see the console update you on the progress it's made. It might hang a bit on the “Starting download…” output because this is where it is downloading the update — so just be patient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AF8E145UGI3s-BmisH5eK-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AF8E145UGI3s-BmisH5eK-g.png" alt="Godot Version Update" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it’s done, it will open the directory where it has installed the update and it will highlight the executable file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9W3Wgkl-FNKZ7I6NpYAwfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9W3Wgkl-FNKZ7I6NpYAwfw.png" alt="Godot Version Update" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AI2oA7M9IqdjX1Ys1_IstVw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AI2oA7M9IqdjX1Ys1_IstVw.png" alt="Godot Version Update" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are on &lt;code&gt;Linux/MacOS/Android&lt;/code&gt;, you will still have to manually extract the folder and open the executable. If you are on &lt;code&gt;Windows&lt;/code&gt;, the plugin will automatically open up your project in the latest version of Godot.&lt;/p&gt;

&lt;p&gt;It might seem that your old version is crashing, but this is just because the project is open in two different versions. Just exit the old version, and it should be fine.&lt;/p&gt;

&lt;p&gt;If everything works, it should open up the latest version, and the “Current Version” value should be the same as the “Latest Version” value!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUnH-C7xChkQeSkAj0g_5Xg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUnH-C7xChkQeSkAj0g_5Xg.png" alt="Godot Version Update" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1015%2F1%2Aq6-yTBZ9-eU8XVCj9cLlHA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1015%2F1%2Aq6-yTBZ9-eU8XVCj9cLlHA.png" alt="Godot Version Update" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, my Godot has been updated from version 4.2.2 to version 4.3 without me having to manually do it on the website. Now whenever I need to update my project, I will just run my blank project with my plugin installed, and click the button. It will automatically fetch the latest version!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F480%2F0%2AUOTS2UfXAbNpIRhj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F480%2F0%2AUOTS2UfXAbNpIRhj.gif" alt="Godot Version Update" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;If you want to use my plugin to upgrade your Godot engine or just try it out, you can download it now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/christinec-dev/GodotVersionUpdater/tree/main/addons/godotversionupdater" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AssetLib (Awaiting Approval)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find bugs in this plugin, please let me know and I will get to fixing the plugin!&lt;/p&gt;

</description>
      <category>plugins</category>
      <category>tools</category>
      <category>godot</category>
    </item>
    <item>
      <title>Going from Godot 3 to 4 (The Easy Way)</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Fri, 09 Aug 2024 10:15:25 +0000</pubDate>
      <link>https://forem.com/christinec_dev/going-from-godot-3-to-4-the-easy-way-1ifc</link>
      <guid>https://forem.com/christinec_dev/going-from-godot-3-to-4-the-easy-way-1ifc</guid>
      <description>&lt;p&gt;When I started learning Godot, I started with Godot 3. When Godot 4 came out, a lot of things changed — especially GDScript. To this day, I still type &lt;code&gt;deg2rad&lt;/code&gt; instead of &lt;code&gt;deg\_to\_rad&lt;/code&gt;, and nothing annoys me more than getting that error &lt;code&gt;"Function "deg2rad()" not found in base self. Did you mean to use "deg\_to\_rad()"?"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You’d think I know better by now, but it’s a habit I can’t break. That’s why I decided to play around with a plugin for Godot to help upgrade your GDScript code from Godot 3 to Godot 4. This plugin automates the process of updating deprecated methods, properties, and syntax, ensuring your projects are compatible with the latest version of Godot.&lt;/p&gt;

&lt;p&gt;All you have to do is download the plugin, add the folder to your project (your project/addons/upgrader/…), activate it, and paste in the code that you want to convert. Easy enough, right? 😅&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmXPooJbM-trGbVaONnI76A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmXPooJbM-trGbVaONnI76A.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, you might not be convinced that this works, so let’s put it to the test by converting one of the very first games I made in Godot 3 to Godot 4 — using only the plugin.&lt;/p&gt;

&lt;p&gt;When I started learning, I came across this YouTube video that showed me how to make a simple farming system. It’s not the best looking and I never even completed the tutorial (wow, another unfinished project), but it made younger me feel like I had the power to make &lt;strong&gt;Stardew Valley 2.0&lt;/strong&gt;. 😎&lt;/p&gt;

&lt;p&gt;Let’s start by seeing what happens when I open my project that was made in Godot 3.2 the latest version of Godot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvaEH8R-B9TMxccuwC9rGtA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvaEH8R-B9TMxccuwC9rGtA.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project setup, the warnings, the blurry textures — it’s giving me the heebie-jeebies. My scripts aren’t organized, my nodes are all over the place- and don’t even get me started on my file management skills. All of these are the artifacts left by beginner me, and I am proud to be the archeologist of this expedition. But we’re not here to critique the project, we’re here to see if the plugin works.&lt;/p&gt;

&lt;p&gt;Before we do that, I’m going to upgrade my textures and fix all of the yellow warnings (mostly StaticBody2D nodes requiring collision shapes).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APlbuoXK2IIRQsXmW0QrvSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APlbuoXK2IIRQsXmW0QrvSQ.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F889%2F1%2ADQHzgvXDT610B6H4Hso5KA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F889%2F1%2ADQHzgvXDT610B6H4Hso5KA.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F943%2F1%2A7eC3fH4_RzzBUtpdzQfZgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F943%2F1%2A7eC3fH4_RzzBUtpdzQfZgw.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Much better! Now let’s see what happens when I try to run my project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AatlBqeYrkd79rnFKucPoCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AatlBqeYrkd79rnFKucPoCg.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uh-oh! I get an error. My scenes can’t run because the scripts all contain outdated code. If only there was a quick fix for that…oh wait, the plugin!&lt;/p&gt;

&lt;p&gt;Let’s download the plugin and enable it in the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A06QRkb7SxEYtLfPEIHV1Sw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A06QRkb7SxEYtLfPEIHV1Sw.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If enabled correctly, there should be a new dock on the left side of the editor. This dock has two parts: a code input and an output panel. We will paste our Godot 3 code in the input panel, and copy our Godot 4 code from the output panel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F541%2F1%2At3NfT7uTqo_O-hD27BH2Nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F541%2F1%2At3NfT7uTqo_O-hD27BH2Nw.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F991%2F1%2A_NYXfbe_oGEY-xQfVCvxfA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F991%2F1%2A_NYXfbe_oGEY-xQfVCvxfA.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s start with our first script, which is our Player script. Here is the code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F702%2F1%2Ak6_RdS5l_4xA8Wl33P2POQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F702%2F1%2Ak6_RdS5l_4xA8Wl33P2POQ.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it uses &lt;code&gt;KinematicBody3D&lt;/code&gt; and &lt;code&gt;move_and_slide()&lt;/code&gt; with a parameter motion. In Godot 4, &lt;code&gt;move_and_slide()&lt;/code&gt; does not call a parameter, and &lt;code&gt;KinematicBody2D&lt;/code&gt; becomes &lt;code&gt;CharacterBody2D&lt;/code&gt;. Let’s see if the plugin can detect these errors and fix it.&lt;/p&gt;

&lt;p&gt;Paste in old code and press “Execute”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F497%2F1%2Ag5Ftuq-n83UHc14cvobU8Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F497%2F1%2Ag5Ftuq-n83UHc14cvobU8Q.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New code should be upgraded automatically:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F498%2F1%2ArF1bBEz3wkV9serw236Uzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F498%2F1%2ArF1bBEz3wkV9serw236Uzw.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it made the fixes automatically. Let’s paste these changes into our script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F664%2F1%2Aj1ij84jHtIfcvYoh5JHJag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F664%2F1%2Aj1ij84jHtIfcvYoh5JHJag.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No more errors! Okay, let’s do another script. The next script is used to “plant” seeds on a plot of land. As you can see below, it uses &lt;code&gt;BUTTON_LEFT&lt;/code&gt; when it should be &lt;code&gt;MOUSE_BUTTON_LEFT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F665%2F1%2AL8xl46UHUDTzgA-mLRawKQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F665%2F1%2AL8xl46UHUDTzgA-mLRawKQ.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s run it in the upgrader:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F500%2F1%2AUy3Ys7YAYJMB1pUjSUNIBw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F500%2F1%2AUy3Ys7YAYJMB1pUjSUNIBw.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F685%2F1%2Ac5Voo0cR2nnEmTOTrz_1RQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F685%2F1%2Ac5Voo0cR2nnEmTOTrz_1RQ.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see it made the fixes and no more errors. Let’s do some more. Below it uses &lt;code&gt;rand_range&lt;/code&gt;, when in Godot 4 it would be &lt;code&gt;randf_range&lt;/code&gt; (for floats) or &lt;code&gt;randi_range&lt;/code&gt; (for ints). The plugin made the conversion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F684%2F1%2A4Mo0hWiP_5qShWNbbuqU8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F684%2F1%2A4Mo0hWiP_5qShWNbbuqU8g.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F495%2F1%2ALEzx-mzyqSW-dh95y7h73g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F495%2F1%2ALEzx-mzyqSW-dh95y7h73g.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F846%2F1%2A3GHsCA5DEYimNnmSrkX-hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F846%2F1%2A3GHsCA5DEYimNnmSrkX-hw.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! One last one. The code below uses the old method of reading JSON files. The converter will not fully be able to replace your code, as your layout might differ, but it will give you a guide on how to do it. All you have to do is remove your old code, uncomment the guide, and copy in your file path. It’s easy!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F901%2F1%2AnpWVI_xDqhpYsQv48uK3CA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F901%2F1%2AnpWVI_xDqhpYsQv48uK3CA.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F448%2F1%2Ao4AhrS8aB3d5RMcpMf5ksg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F448%2F1%2Ao4AhrS8aB3d5RMcpMf5ksg.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F903%2F1%2AgEr5H1XKYLofzz-HODYg3A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F903%2F1%2AgEr5H1XKYLofzz-HODYg3A.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F840%2F1%2AWCEL_W46pD988-KfvX-AQA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F840%2F1%2AWCEL_W46pD988-KfvX-AQA.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the code fixes out of the way, let’s run the code to see if it works. As I said, I never finished the tutorial, so all I could do in this project was drag seeds over the land to plant them and then after a few seconds they started to grow. Don’t judge me before you look at all the unfinished projects you might have. 😅&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKcE3t2qsFTGHH-hoiLNmvQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKcE3t2qsFTGHH-hoiLNmvQ.gif" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With my project working, I can now go back and add the finishing details, and Stardew Valley 2.0 will be live and ready to be published on Steam. Wish me luck! 😄&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AIa9V-4QP8deVCZbetI_inA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AIa9V-4QP8deVCZbetI_inA.png" alt="Godot Code Upgrader Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;If you want to use my plugin to upgrade your code or just try it out, you can &lt;strong&gt;download&lt;/strong&gt; it now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/christinec-dev/GDScriptCodeUpgrader" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://godotengine.org/asset-library/asset/3217" rel="noopener noreferrer"&gt;AssetLib&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please know that I might not have picked up all the changes, as there are a lot, so if you find ones that I haven’t added, you can let me know and I will implement those fixes into the plugin!&lt;/p&gt;

</description>
      <category>godot</category>
      <category>godotengine</category>
      <category>plugins</category>
      <category>tooling</category>
    </item>
    <item>
      <title>The Book of Nodes: 2D</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Wed, 07 Aug 2024 12:44:25 +0000</pubDate>
      <link>https://forem.com/christinec_dev/the-book-of-nodes-2d-3dkg</link>
      <guid>https://forem.com/christinec_dev/the-book-of-nodes-2d-3dkg</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below you can find a list of 2D nodes that can be used in Godot 4. This is part of my &lt;a href="https://dev.to/christinec_dev/the-book-of-nodes-1p9c"&gt;Book of Nodes&lt;/a&gt; series. If you want to see similar content on 3D or UI nodes, please refer to the parent page of this post for those links. 😊&lt;/p&gt;

&lt;p&gt;Before we begin, if you need a base project to test these code snippets, feel free to download my FREE 2D and 3D templates &lt;a href="https://christinecdevs.site/2d-3d-prototype-templates/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I’ll be using these templates throughout this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*Please note that this list is not 100% complete yet, but I will be updating this list as time goes on.&lt;/em&gt;&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AnimatedSprite2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AnimationPlayer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AnimationTree&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Area2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AudioStreamPlayer2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Camera2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CharacterBody2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CollisionShape2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DirectionalLight2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LightOccluder2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MeshInstance2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NavigationAgent2D, NavigationObstacle2D, NavigationRegion2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Path2D, PathFollow2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PointLight2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RayCast2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RigidBody2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sprite2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StaticBody2D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TileMap&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Node2D
&lt;/h1&gt;

&lt;p&gt;The Node2Dnode is the fundamental building block for all 2D scenes in Godot. It provides us with basic 2D spatial features like position, rotation, and scale. Almost all 2D nodes (like Sprite2D, Area2D, etc.) inherit from Node2D, which makes it the most essential node for any 2D game development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AMMWVOG8FurF4WXSbfbmB5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AMMWVOG8FurF4WXSbfbmB5w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Move a group of 2D nodes collectively.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Node2D to your scene to serve as a parent node. This could represent a game object like a vehicle or a character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F419%2F1%2A4jxVEg5bM6mjFndNOmID0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F419%2F1%2A4jxVEg5bM6mjFndNOmID0w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add child nodes such as twoSprite2Dnodes. These children can represent visual components, collision areas, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcpNoHXemEF4gEKilAYfA-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcpNoHXemEF4gEKilAYfA-g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Inspector, assign a texture (image file) of your choosing to the texture property of the Sprite2D node. This image will be what is displayed in the scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVlYcx0OJ5TUYhY-J5m7bVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVlYcx0OJ5TUYhY-J5m7bVQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now if we manipulate the Node2D parent, it will affect all its children. For example, moving the Node2D will move all its children, whilst maintaining their relative positions and transformations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F498%2F1%2A-MvjPol_BaGTiFks4UIjIg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F498%2F1%2A-MvjPol_BaGTiFks4UIjIg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can also do this via code — say if we press SPACE on our keyboard, the node moves -100 pixels on the x-axis.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var node_2d = $Node2D

func _process(delta):
 if Input.is_action_pressed("ui_select"):
  node_2d.position.x -= 100 * delta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F558%2F1%2Ahz1CffZfezs8-3hOhrLHbQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F558%2F1%2Ahz1CffZfezs8-3hOhrLHbQ.gif" alt="Book of Nodes" width="558" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Sprite2D
&lt;/h1&gt;

&lt;p&gt;The Sprite2Dnode in Godot is used to display 2D images in your scenes. Since it inherits from the Node2Dnode, it can handle various transformations like scaling, rotation, and translation. It’s one of the most commonly used nodes for representing characters, objects, and other visual elements in a 2D space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ALtAikMkrbcVGCHOY1ubTFA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ALtAikMkrbcVGCHOY1ubTFA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use either a singular image as the texture, or a tilesheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AIpsVa7TSEQJ1pO9T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AIpsVa7TSEQJ1pO9T.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are using a Tilesheet(as I am in this example) as your texture, you will have to crop out your sprite using the HFramesand VFramesproperty in the Inspector Panel. Then, add a key at each frame. The Frame Coords x property determines which column you are trying to access, and the Frame Coords y property determines which row you are trying to access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqUmT2fLdhQKJl_h8nX9GCA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqUmT2fLdhQKJl_h8nX9GCA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Display and animate a character.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Sprite2D node in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F422%2F1%2AImTdYG5Ujy6fW2XQlT5gtQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F422%2F1%2AImTdYG5Ujy6fW2XQlT5gtQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Inspector, assign a texture (image file) to the texture property of the Sprite2D node. This image will be what is displayed in the scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVCZ9Y_NG9cOwSxMB9kI6XA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVCZ9Y_NG9cOwSxMB9kI6XA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust the position, scale, and rotation properties to position the sprite correctly within your game world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AIUMlUlQihh8D4otbcCYFTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AIUMlUlQihh8D4otbcCYFTQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want to animate the sprite, you can use an AnimationPlayer to animate properties like position, rotation_degrees, and scale. You can also swap out the texture of the Sprite2D if you have a sprite that has multiple animations, for example walking, idling, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkrPxEe36jx3RSAYLQTkhAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkrPxEe36jx3RSAYLQTkhAQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AoiM2jo0S71Rf642S_Pth3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AoiM2jo0S71Rf642S_Pth3g.png" alt="Book of Nodes" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANfe0qWW7RwrLUBVkNJzkMw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANfe0qWW7RwrLUBVkNJzkMw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F564%2F1%2AyDAIU03TcwCzpuVq2aBI4Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F564%2F1%2AyDAIU03TcwCzpuVq2aBI4Q.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the code to play the animation on load.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var animation_player = $AnimationPlayer

func _ready():
 animation_player.play("move_character")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your project and your Sprite2D node should be in your scene. If you added an animation, it should play.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F502%2F1%2A_8j1VDyNvCTFBhdmKZgx1w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F502%2F1%2A_8j1VDyNvCTFBhdmKZgx1w.gif" alt="Book of Nodes" width="502" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AnimatedSprite2D
&lt;/h1&gt;

&lt;p&gt;The AnimatedSprite2D node utilizes a series of images (sprites) and displays them in a sequence to create an animation. Unlike a simple Sprite2D node that displays a single static image, AnimatedSprite2D can cycle through multiple frames to animate characters, objects, or effects within your 2D game. To create these frames, we can use either sprites or a spritesheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AIpsVa7TSEQJ1pO9T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AIpsVa7TSEQJ1pO9T.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AnimatedSprite2D node utilized the SpriteFrames Resource to create animations. This is a special resource in Godot that holds collections of images. Each collection can be configured as an animation by specifying the images (frames) that belong to it. You can create multiple animations within a single SpriteFrames resource, each with its own set of frames and playback properties like speed and loop settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A2unPwBL5wpitA2KG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A2unPwBL5wpitA2KG.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A2t3UNo7uKP4rl7X2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A2t3UNo7uKP4rl7X2.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a character with walking animations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create an AnimatedSprite2D node in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F420%2F0%2AWQkpkgNq-QMF4Zwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F420%2F0%2AWQkpkgNq-QMF4Zwx.png" alt="Book of Nodes" width="420" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a SpriteFrames resource to the AnimatedSprite2D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F464%2F0%2AiZtnN9Wzpz4kwCto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F464%2F0%2AiZtnN9Wzpz4kwCto.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F463%2F0%2A05xx1cS1pAQ9xqD5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F463%2F0%2A05xx1cS1pAQ9xqD5.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a new animation by clicking on the page+ icon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F258%2F0%2ArHjUExFn29eA6sJ0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F258%2F0%2ArHjUExFn29eA6sJ0.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rename this animation by double-clicking on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1015%2F0%2A7jIxwXStyGf1irv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1015%2F0%2A7jIxwXStyGf1irv7.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either drag in sprites into the frames box or click the spritesheet icon to add animations via an atlas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1003%2F0%2Ay_k53LDhpemmP4R5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1003%2F0%2Ay_k53LDhpemmP4R5.png" alt="Book of Nodes" width="800" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crop out the frames horizontally and vertically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AmXKCCWfTPCVv17Ai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AmXKCCWfTPCVv17Ai.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the frames you want. For instance, in my person atlas, I will choose frames 0–6 in row 5.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A7bZNW3kRxecM7Xn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A7bZNW3kRxecM7Xn9.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then play the animation to see if you need to alter the FPS to make the character move faster/slower:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1010%2F0%2AhNCT7XDMjFdGEs8H.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1010%2F0%2AhNCT7XDMjFdGEs8H.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeat the process for all of your animations, for example walk_left, walk_up, walk_down, walk_up, idle_x, run_x, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1020%2F0%2AKit_I54AoAfcG3Q2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1020%2F0%2AKit_I54AoAfcG3Q2.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play the animation in your code so that when your player moves during runtime the animation can play:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody2D

# Scene-Tree Node references
@onready var animated_sprite = $AnimatedSprite2D

# Variables
@export var speed = 100

# Input for movement
func get_input():
 var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
 velocity = input_direction * speed

# Movement &amp;amp; Animation
func _physics_process(delta):
 get_input()
 move_and_slide()
 update_animation()

# Animation
func update_animation():
 if velocity == Vector2.ZERO:
  animated_sprite.play("idle")
 else:
  if abs(velocity.x) &amp;gt; abs(velocity.y):
   if velocity.x &amp;gt; 0:
    animated_sprite.play("walk_right")
   else:
    animated_sprite.play("walk_left")
  else:
   if velocity.y &amp;gt; 0:
    animated_sprite.play("walk_down")  
   else:
    animated_sprite.play("walk_up")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your project and move around:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F398%2F1%2AsahPpQfYULa5NqtKVVj8CQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F398%2F1%2AsahPpQfYULa5NqtKVVj8CQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AnimationPlayer
&lt;/h1&gt;

&lt;p&gt;Unlike the AnimatedSprite2D which is specifically designed for sprite animations, the AnimationPlayer can animate virtually ANY node within a Godot scene. Instead of animating a simple sprite, you can animate the node’s properties — including but not limited to positions, rotations, scales, colors, and even variables.&lt;/p&gt;

&lt;p&gt;The AnimationPlayer can hold a set of animations on a singular timeline, each containing keyframes that define the start and end points of any property that changes over time. You can create complex sequences and control animations in a non-linear fashion.&lt;/p&gt;

&lt;p&gt;This node can be used to animate 2D, 3D, and even UI nodes!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Abn2akzwuRF3evvn2bCCZgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Abn2akzwuRF3evvn2bCCZgQ.png" alt="Book of Nodes" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvD9XpLTs_iyaRZ52jPB0rA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvD9XpLTs_iyaRZ52jPB0rA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Animate a Sprite2D node of a potion that pulses in size to capture player's attention.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Sprite2D node and an AnimationPlayer node to your scene. The Sprite2D node is the node we want to animate, and the property we want to animate of this node is its scale.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F421%2F1%2Ax2XP0MOh0vfn89ZaHAJNsA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F421%2F1%2Ax2XP0MOh0vfn89ZaHAJNsA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a sprite to the Sprite2D node. I’ll assign a potion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F477%2F1%2AtO6GbWVmiOSRtC76-YBWZQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F477%2F1%2AtO6GbWVmiOSRtC76-YBWZQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the AnimationPlayer node.&lt;/li&gt;
&lt;li&gt;In the animation panel, click “New Animation” and name it something descriptive like “pulse”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F341%2F1%2AOjbyCQuO6-GGtv9SvwgXaQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F341%2F1%2AOjbyCQuO6-GGtv9SvwgXaQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F986%2F1%2A3JIgLsrhgB9wtOyrr-0fKg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F986%2F1%2A3JIgLsrhgB9wtOyrr-0fKg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the animation length to the duration you want for one pulse cycle (e.g., 1 second).&lt;/li&gt;
&lt;li&gt;Enable the “Loop” option to make the animation repeat continuously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1002%2F1%2Ab6OuXK71qm2AfC9zFClWUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1002%2F1%2Ab6OuXK71qm2AfC9zFClWUw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the beginning of the animation timeline (0 seconds).&lt;/li&gt;
&lt;li&gt;Select the Sprite2D node, and in the Inspector, set the scale property to its initial value (e.g., Vector2(1, 1)).&lt;/li&gt;
&lt;li&gt;Right-click the scale property in the Inspector and select "Key" to add a keyframe.&lt;/li&gt;
&lt;li&gt;Move to the middle of the timeline (e.g., 0.5 seconds), change the scale to a larger value (e.g., Vector2(1.2, 1.2)), and add another keyframe.&lt;/li&gt;
&lt;li&gt;At the end of the timeline (1 second), set the scale back to the initial value (Vector2(1, 1)) and add a final keyframe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F473%2F1%2AAzPAk1QzC3FxeFZiN_jF6A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F473%2F1%2AAzPAk1QzC3FxeFZiN_jF6A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATFpV4IW0XrYAaejRXrQ2Iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATFpV4IW0XrYAaejRXrQ2Iw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArI_09OsPWCsO_a7md0QeSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArI_09OsPWCsO_a7md0QeSQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcjTEmx_nUZ6uLG-DA8oX8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcjTEmx_nUZ6uLG-DA8oX8w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can control when the animation starts or stops via script, or let it run continuously since it’s set to loop.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

@onready var animation_player = $AnimationPlayer

func _ready():
    animation_player.play("pulse")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Start your project and observe the potion sprite pulsing in size.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F690%2F1%2A7fIETboY9qU7aeCj99UpaQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F690%2F1%2A7fIETboY9qU7aeCj99UpaQ.gif" alt="Book of Nodes" width="690" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  MeshInstance2D
&lt;/h1&gt;

&lt;p&gt;The MeshInstance2D node is used for displaying a Meshin a 2D space. In Godot, a mesh is used as a resource that can be applied to MeshInstance nodes to render geometry in a scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AfjhrswDkoGOPGVG4Ylw5Qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AfjhrswDkoGOPGVG4Ylw5Qw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be particularly useful for achieving effects or visual styles that are difficult with standard 2D sprites or animations, such as deformations or complex shading that reacts to lighting conditions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Dynamically deform a 2D mesh (Sprite2D conversion).&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Sprite2D node in your scene. Assign it with a texture of your choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Asa2_ZjYueaPRRS7PK_66oA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Asa2_ZjYueaPRRS7PK_66oA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the editor’s conversion tool to convert it to MeshInstance2D node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F646%2F1%2AcKvtPxKJ4F2HivsRKmpAwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F646%2F1%2AcKvtPxKJ4F2HivsRKmpAwg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A dialog will appear, showing a preview of how the 2D mesh will be created. The yellow lines are the mesh polygons — and this will make up your 2D mesh shape. The default values are fine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F904%2F1%2AbX3vm-DcYh7dAFacW6N0jA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F904%2F1%2AbX3vm-DcYh7dAFacW6N0jA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Sprite2Dnode should be converted into a MeshInstance2Dnode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AHoYxHyMzRMsyWRKnwkLIfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AHoYxHyMzRMsyWRKnwkLIfw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use scripts to deform the mesh dynamically.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var sprite_2d = $Sprite2D

func _process(delta):
    var scale_factor = sin(Time.get_ticks_msec() / 1000.0) * 0.1 + 1.0
    sprite_2d.scale = Vector2(scale_factor, scale_factor)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene to observe the 2D mesh dynamically deform itself!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F546%2F1%2A0XHMDo3957FlPnilyQNtKw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F546%2F1%2A0XHMDo3957FlPnilyQNtKw.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AnimationTree
&lt;/h1&gt;

&lt;p&gt;The AnimationTree node enhances the capabilities of the AnimationPlayer by providing advanced features for animations, such as blending, transitions, and states. This makes it extremely easy to make detailed character animations and interactive scene elements in 2D and 3D environments.&lt;/p&gt;

&lt;p&gt;We usually use blending to create smooth transitions between animations, for example, smoothly transitioning between walking and running depending on the player’s speed.&lt;/p&gt;

&lt;p&gt;We use state machines to switch our animations dynamically depending on the conditions, for example, switching between idle and attack animations if the player presses a key.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Animate a 2D character with multiple actions (e.g., walking, idle).&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add an AnimationPlayernode to your scene and create animations for it like "walk_x”, "idle". You’ll need to create these animations from a Sprite2Dnode, or else it won’t work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AigN-0hrXGEXkYhF51Sbcfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AigN-0hrXGEXkYhF51Sbcfg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqDPPLHvyeXtmMgttFG0TIg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqDPPLHvyeXtmMgttFG0TIg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, add an AnimationTree node, linking it to the AnimationPlayer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F421%2F1%2AIpw2-cw07BU7Dbb8_u16zQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F421%2F1%2AIpw2-cw07BU7Dbb8_u16zQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure the tree_root as an AnimationNodeStateMachine for managing states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F557%2F1%2AV8_slCifFsYtLJLDHLe7tg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F557%2F1%2AV8_slCifFsYtLJLDHLe7tg.png" alt="Book of Nodes" width="557" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also assign the AnimationPlayeras the Anim Player property because this is where our AnimationTree will call the animations from, and the Advanced Expression as the root node because this is where our animation coding can be found (our script).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F590%2F1%2Ak5VAHSkZ5xpgAd68PCnFFg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F590%2F1%2Ak5VAHSkZ5xpgAd68PCnFFg.png" alt="Book of Nodes" width="590" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you open your AnimationTree, you will see if you right-click you can add animations, blend trees, and state machines. Add your ‘idle’ animation and a BlendSpace2Dso that we can play our walk animations depending on our player's Vector2() coordinates. Rename the BlendSpace2D to ‘walk’.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F952%2F1%2AQD10LziT4q0XjJFWv7nPzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F952%2F1%2AQD10LziT4q0XjJFWv7nPzg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2CJZW0s9cAzghyK61WitfA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2CJZW0s9cAzghyK61WitfA.png" alt="Book of Nodes" width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a transition between start -&amp;gt; idle. The transition type should be immediatebecause we want the animation to play immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F398%2F1%2A80PT-jFDwI0lkmFYvyCzzQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F398%2F1%2A80PT-jFDwI0lkmFYvyCzzQ.png" alt="Book of Nodes" width="398" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the pencil icon to edit your walk BlendSpace2D. Then add a point with an animation at each coordinate. Up (0, -1). Down (0, 1). Left (-1, 0). Right (1, 0). Idle (0,0). Also change the blend mode to “Discrete”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxTqzV_T75bHcPiNXnl4GCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxTqzV_T75bHcPiNXnl4GCg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aw870DfaxsTat_Mv4yax25g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aw870DfaxsTat_Mv4yax25g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add transitions between idle -&amp;gt; walk and vice versa. The transition type for both should be syncbecause we want to blend the animation. Also set the mode to enabledbecause we will activate this animation via the code, and not automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F505%2F1%2A86YunkK0y_YPbxUM5oOY2A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F505%2F1%2A86YunkK0y_YPbxUM5oOY2A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAD-S5R_wPsU03W-U7rhGSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAD-S5R_wPsU03W-U7rhGSA.png" alt="Book of Nodes" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now in our code, we can play our animations based on our input.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody2D

# Scene-Tree Node references
@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")

# Variables
@export var speed = 100

# Input for movement
func get_input():
 var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
 velocity = input_direction * speed

# Movement &amp;amp; Animation
func _physics_process(delta):
 get_input()
 move_and_slide()
 update_animation()

# Animation
func update_animation():
 var blend_position = Vector2.ZERO
 if velocity == Vector2.ZERO:
  animation_state.travel("idle")
 else:
  blend_position = velocity.normalized()
  animation_state.travel("walk")

 animation_tree.set("parameters/walk/blend_position", blend_position)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and control the character to observe the transitions and movement based on our state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F756%2F1%2A1pP65F8ZEYzGfLp4SyMCvw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F756%2F1%2A1pP65F8ZEYzGfLp4SyMCvw.gif" alt="Book of Nodes" width="560" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  CollisionShape2D
&lt;/h1&gt;

&lt;p&gt;The CollisionShape2D node allows you to specify the boundaries of an object for collision detection, which is essential for handling interactions between objects in your game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU_iJ3Nc8inSCD6v2XhHACg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU_iJ3Nc8inSCD6v2XhHACg.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Add a collision area to block the character from passing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a CollisionShape2D node as a child of a CharacterBody2D, RigidBody2D, orStaticBody2D. These nodes will block other collisions. To have a node pass through collisions, use an Area2D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F385%2F1%2Avw2Al71Zzlsy6422ksIufg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F385%2F1%2Avw2Al71Zzlsy6422ksIufg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F401%2F1%2AJNrbUmFsQB7vFEqASDDFfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F401%2F1%2AJNrbUmFsQB7vFEqASDDFfw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Inspector, assign a Shape2D resource to the shape property of the CollisionShape2D. The shape you choose will depend on the shape of your entity. For example, a player might have a capsule shape, a pickup a circle, an area a box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcW1e66FnDXtnd6y6EzyxIA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcW1e66FnDXtnd6y6EzyxIA.png" alt="Book of Nodes" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let’s enable debugging to see our collisions in action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F419%2F1%2ANOSd3fnTzxguxb6hyRIROA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F419%2F1%2ANOSd3fnTzxguxb6hyRIROA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene to see how your player interacts with the collision shape. Since we used a StaticBody2D node, they should be blocked and unallowed to go through the collision.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F566%2F1%2AfCHd4fNg_r4dIt5mdSfeKg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F566%2F1%2AfCHd4fNg_r4dIt5mdSfeKg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  CharacterBody2D
&lt;/h1&gt;

&lt;p&gt;The CharacterBody2D node is a specialized class for physics bodies that are meant to be controlled or moved around by the user. Unlike other physics bodies such as the RigidBody2Dor StaticBody2Dnode, CharacterBody2Dis not affected by the engine’s physics properties like gravity or friction by default. Instead, you have to write code to control its behavior, giving you precise control over how it moves and reacts to collisions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Move a character with arrow keys, including handling gravity and jumping.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a CharacterBody2D node to your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F402%2F1%2A6RFwLWh2DIJesLAAgCRiDA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F402%2F1%2A6RFwLWh2DIJesLAAgCRiDA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see it has a warning icon next to it. This is because it needs a collision shape to be able to interact with the world. Add a CollisionShape2D as a child of the CharacterBody2D and set its shape to match your character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AbqgcJ3qjr3zdkgIRfysXGw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AbqgcJ3qjr3zdkgIRfysXGw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a Sprite2D node to this scene so that we can see our character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7gGgVMPYVgLvct4b6KNvwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7gGgVMPYVgLvct4b6KNvwA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach a script to the CharacterBody2D to handle movement and jumping.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody2D

# Variables
@export var speed = 200
@export var jump_force = -400
@export var gravity = 800

# Input for movement
func get_input():
 velocity.x = 0
 if Input.is_action_pressed("ui_right"):
  velocity.x += speed
 if Input.is_action_pressed("ui_left"):
  velocity.x -= speed
 if Input.is_action_pressed("ui_down"):
  velocity.y -= jump_force
 if is_on_floor() and Input.is_action_just_pressed("ui_up"):
  velocity.y = jump_force

# Movement &amp;amp; Gravity
func _physics_process(delta):
 get_input()
 velocity.y += gravity * delta
 move_and_slide()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and use the arrow keys to move the character and make it jump.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F370%2F1%2AFTlWou62Qhm1I1zjEeROzA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F370%2F1%2AFTlWou62Qhm1I1zjEeROzA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  StaticBody2D
&lt;/h1&gt;

&lt;p&gt;The StaticBody2D node is used to represent objects that do not move. This node is ideal for creating static elements in your game, such as walls, floors, and other immovable objects such as chests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create an obstacle.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a StaticBody2D node in your scene. Add a CollisionShape2Das a child of the StaticBody and set its shape to match the obstacle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aei2nqITVwaLWigbe4irdUQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aei2nqITVwaLWigbe4irdUQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a Sprite2D of your choice so that we can see the item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3zRfbwB8ECfSy5qvwb1XRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3zRfbwB8ECfSy5qvwb1XRQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene to see how your player interacts with the collision shape. They should be blocked and unallowed to go through the obstacle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F424%2F1%2A1bg58y6A7EDXLh9wn0zScg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F424%2F1%2A1bg58y6A7EDXLh9wn0zScg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  RigidBody2D
&lt;/h1&gt;

&lt;p&gt;The RigidBody2D node is used for objects that are affected by the engine’s physics. These bodies can move, rotate, and respond to forces and collisions. They are ideal for creating dynamic objects that need realistic physics interactions, such as balls, bullets, moveable obstacles, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a moveable obstacle.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a RigidBody2D node in your scene. Add a CollisionShape2Das a child of the RigidBody and set its shape to match the obstacle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4O1rQmPgeHKh7KInlDfgQA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4O1rQmPgeHKh7KInlDfgQA.png" alt="Book of Nodes" width="800" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a Sprite2D of your choice so that we can see the item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0lqBEXa_F2Uq6PPJLY3Jbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0lqBEXa_F2Uq6PPJLY3Jbw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since we want to move this item when our player collides with it, we should disable its gravity so that it doesn’t get pulled downwards (unless you are making a 2D platformer).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F555%2F1%2ADqNwMQC4oSQRhVxOrbYNFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F555%2F1%2ADqNwMQC4oSQRhVxOrbYNFQ.png" alt="Book of Nodes" width="555" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use GDScript to apply forces or impulses to the rigid body if the player pushes it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody2D

# Scene-Tree Node references
@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")

# Variables
@export var speed = 100
@export var push_force = 80.0

# Input for movement
func get_input():
 var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
 velocity = input_direction * speed

# Movement &amp;amp; Animation
func _physics_process(delta):
 get_input()
 move_and_slide()
 update_animation()
 handle_collisions()

# Animation
func update_animation():
 var blend_position = Vector2.ZERO
 if velocity == Vector2.ZERO:
  animation_state.travel("idle")
 else:
  blend_position = velocity.normalized()
  animation_state.travel("walk")

 animation_tree.set("parameters/walk/blend_position", blend_position)

# Handle Collisions
func handle_collisions():
 for i in range(get_slide_collision_count()):
  var collision = get_slide_collision(i)
  if collision.get_collider() is RigidBody2D:
   var collider = collision.get_collider() as RigidBody2D
   var impulse = -collision.get_normal() * push_force
   collider.apply_central_impulse(impulse)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and observe how the obstacle moves when the player pushes against it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F586%2F1%2AMF-g1Oz5-Mr-a10A0T46Gw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F586%2F1%2AMF-g1Oz5-Mr-a10A0T46Gw.gif" alt="Book of Nodes" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Area2D
&lt;/h1&gt;

&lt;p&gt;The Area2D node is used to detect when objects enter or exit a defined area. They do not represent physical bodies but are useful for triggering events such as cutscenes or map transitions, detecting overlaps, and creating zones for things such as enemy or loot spawning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A8LV6cwLaG3BA6bFWXZ11rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A8LV6cwLaG3BA6bFWXZ11rg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use the Area2D node’s on_body_entered() and on_body_exited() signals to determine whether or not a PhysicsBody has entered this zone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmBQh-XhpM3ACQKsKQ1d1uw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmBQh-XhpM3ACQKsKQ1d1uw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a trigger zone that detects when the player enters a specific area.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create an Area2D node in your scene. You also need to add a CollisionShape2D as a child of the Area and set its shape to define the trigger zone. Adjust the collision shape's properties to fit the dimensions of your trigger zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F406%2F1%2AMElhKLCXRlw5KFruBVB1cQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F406%2F1%2AMElhKLCXRlw5KFruBVB1cQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ay1zyKyiGbNmcdjSIAUW63g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ay1zyKyiGbNmcdjSIAUW63g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach the Area2D node’s on_body_entered() and on_body_exited() signals to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1016%2F1%2AFR70wn_hjSsS9h_WMsSnfQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1016%2F1%2AFR70wn_hjSsS9h_WMsSnfQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1014%2F1%2AbF11nyJqPXcOjCGp7LyNtw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1014%2F1%2AbF11nyJqPXcOjCGp7LyNtw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use GDScript to notify us when the Player enters or exits the area.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

func _on_area_2d_body_entered(body):
 if body.name == "Player":
  print("The player has entered the area!")

func _on_area_2d_body_exited(body):
 if body.name == "Player":
  print("The player has exited the area!")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable debugging so we can see when our Player enters/exits our area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F404%2F1%2A5tODHdR-eC7PlIYqPPQYTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F404%2F1%2A5tODHdR-eC7PlIYqPPQYTQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the scene and observe how the area detects when the Player enters or exits the defined zone. Each time the player enters/exits the zone, the game should be notified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F494%2F1%2AuGIGwCuxcaYO7Hy6xQknfA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F494%2F1%2AuGIGwCuxcaYO7Hy6xQknfA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F948%2F1%2AJlyriH1WKNJGJQEVFHGTog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F948%2F1%2AJlyriH1WKNJGJQEVFHGTog.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  RayCast2D
&lt;/h1&gt;

&lt;p&gt;The RayCast2D node is used to cast a ray in a 2D space to detect objects along its path. This is useful for various purposes such as line-of-sight checks, shooting and attacking mechanics, and collision detection.&lt;/p&gt;

&lt;p&gt;It can collide with &lt;strong&gt;bodies&lt;/strong&gt; such as StaticBody2D (useful for detecting loot and quest items), CharacterBody2D (useful for detecting interactions with enemies and NPCs), and RigidBody2D (useful for detecting interactions with moveable objects. It can also collide with &lt;strong&gt;areas&lt;/strong&gt; , such as Area2D (useful for interactions with trigger zones).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANqUgtKtaqQAca45ezlkefw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANqUgtKtaqQAca45ezlkefw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Cast a ray from the player and detect what it hits.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a RayCast2D node to the Player in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU4lt9Bj4b_U9b7mRP9dQGQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU4lt9Bj4b_U9b7mRP9dQGQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the target_position property to define the direction and length of the ray. I usually leave mine at its default values. You can also enable its collision with areas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARt5rhlU25YxvBX_9_uLTEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARt5rhlU25YxvBX_9_uLTEQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the code, let’s update our raycast to always face the player’s last direction. We will also print the colliders it’s hitting.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody2D

# Scene-Tree Node references
@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")

# Variables
@export var speed = 100
var direction = Vector2()
@onready var ray_cast_2d = $RayCast2D

# Input for movement
func get_input():
 var input_direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
 direction = input_direction
 velocity = input_direction * speed

# Raycast hit detection
func _process(delta):
 if ray_cast_2d.is_colliding():
  var collider = ray_cast_2d.get_collider()
  print("Raycast hit: ", collider.name)

# Movement &amp;amp; Animation
func _physics_process(delta):
 get_input()
 move_and_slide()
 update_animation()

 # Update raycast to face player direction
 if direction != Vector2.ZERO:
  ray_cast_2d.target_position = direction.normalized() * 50

# Animation
func update_animation():
 var blend_position = Vector2.ZERO
 if velocity == Vector2.ZERO:
  animation_state.travel("idle")
 else:
  blend_position = velocity.normalized()
  animation_state.travel("walk")

 animation_tree.set("parameters/walk/blend_position", blend_position)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and interact with objects that have colliders. The raycast should detect the objects and notify the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F998%2F1%2AJWKbO_ejNMsrbTVFvAv0eQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F998%2F1%2AJWKbO_ejNMsrbTVFvAv0eQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F913%2F1%2AE3b-JUguP3IYLQAuA-uR5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F913%2F1%2AE3b-JUguP3IYLQAuA-uR5w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Camera2D
&lt;/h1&gt;

&lt;p&gt;The Camera2D node is used to control the view of a 2D scene. It allows the screen to follow the player or other objects. Only one Camera can be active per viewport, and it registers itself in the nearest Viewport node.&lt;/p&gt;

&lt;p&gt;In 2D games, we usually attach the Camera2D node to either the Player or our World scene. Attach it to the Player if you want to follow the player around. Attach the Camera to your World (Main) scene if you want a birds-eye view of the environment. This usually requires a bit more configuration and coding, as you have to make the camera able to move, rotate, scroll, or zoom around the scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmrmlBStYpV3qnvCzvOmL1Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmrmlBStYpV3qnvCzvOmL1Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a “God Mode” 2D camera that can move, zoom, and rotate based on user input.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Camera2D node to your Main (World) scene. Make sure this camera is enabled, and all other cameras are disabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F389%2F1%2A2RC7EwG8tY2XJ3afdcsnQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F389%2F1%2A2RC7EwG8tY2XJ3afdcsnQg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the inputs to zoom and rotate your camera. The default up, down, left, and right inputs should be fine to move the camera.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsaGwiOeq9TKlltWzD-zDGA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsaGwiOeq9TKlltWzD-zDGA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxF7MnBzFGx3zB_RmgAqP5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxF7MnBzFGx3zB_RmgAqP5g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use GDScript to handle the camera’s zoom, movement, and rotation. You can do this in a custom Camera.gd script (preferred), or directly in your root script.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var camera_2d = $Camera2D
@export var zoom_speed = 0.5
@export var move_speed = 200
@export var rotate_speed = 0.5
@export var min_zoom = 0.5
@export var max_zoom = 2.0

func _process(delta):
 handle_zoom(delta)
 handle_movement(delta)
 handle_rotation(delta)

# Zooming
func handle_zoom(delta):
 if Input.is_action_pressed("zoom_out"):
  camera_2d.zoom -= Vector2(zoom_speed, zoom_speed) * delta
 if Input.is_action_pressed("zoom_in"):
  camera_2d.zoom += Vector2(zoom_speed, zoom_speed) * delta
 camera_2d.zoom.x = clamp(camera_2d.zoom.x, min_zoom, max_zoom)
 camera_2d.zoom.y = clamp(camera_2d.zoom.y, min_zoom, max_zoom)

# Moving
func handle_movement(delta):
 var direction = Vector2.ZERO
 if Input.is_action_pressed("ui_right"):
  direction.x += 1
 if Input.is_action_pressed("ui_left"):
  direction.x -= 1
 if Input.is_action_pressed("ui_down"):
  direction.y += 1
 if Input.is_action_pressed("ui_up"):
  direction.y -= 1
 camera_2d.position += direction.normalized() * move_speed * delta

# Rotating
func handle_rotation(delta):
 if Input.is_action_pressed("rotate_left"):
  camera_2d.rotation -= rotate_speed * delta
 if Input.is_action_pressed("rotate_right"):
  camera_2d.rotation += rotate_speed * delta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and use the defined input actions to move, zoom, and rotate the camera.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F492%2F1%2AMr5YZXt1MclwHGKNxzB02A.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F492%2F1%2AMr5YZXt1MclwHGKNxzB02A.gif" alt="Book of Nodes" width="200" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  DirectionalLight2D
&lt;/h1&gt;

&lt;p&gt;The DirectionalLight2D node is used to simulate sunlight or moonlight. It emits light in a specific direction, affecting all objects in the scene equally, regardless of their distance from the light source. This type of light is useful for outdoor scenes where you need consistent lighting across the entire scene.&lt;/p&gt;

&lt;p&gt;This node’s two main properties are the energy and color properties. The energy property determines how bright/dim the light is, and the color is the shading of the light.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASen7JrZNvyYuo_XeybakIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASen7JrZNvyYuo_XeybakIQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, I prefer &lt;strong&gt;NOT&lt;/strong&gt; to use this node without shaders because its features are a bit unfinished (and the shadows are not good). If you’d like an introductory tutorial on how to use this node with shaders ( by making a day and night cycle), please check out my &lt;a href="https://github.com/christinec-dev/DayNightCycleGodot" rel="noopener noreferrer"&gt;YouTube video&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Illuminate a scene with sunlight.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Create a DirectionalLight2D node in your scene.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4SwH5VjNWh_heRYLsZr_IA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4SwH5VjNWh_heRYLsZr_IA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As you can see, this is crazy bright. Let’s adjust our properties like energy andcolorto customize the light's appearance and behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F599%2F1%2Aho7LjzOpK1wUkteb9SIQ_g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F599%2F1%2Aho7LjzOpK1wUkteb9SIQ_g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZei6xPdVIC-qjwWvzgkFjQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZei6xPdVIC-qjwWvzgkFjQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now let’s do something fun. I recommend using shaders with this node, but just for testing sake, let’s have it randomize its color each second.&lt;/li&gt;
&lt;li&gt;Add a Timer node to your scene. In the Inspector Panel, enable autostart, and connect its timeout signal to your script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F401%2F1%2ASLoxAf2p9IS5QhSc_G2Zbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F401%2F1%2ASLoxAf2p9IS5QhSc_G2Zbg.png" alt="Book of Nodes" width="401" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F576%2F1%2ATeUoA8w2u5Avz4nCLpq8aQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F576%2F1%2ATeUoA8w2u5Avz4nCLpq8aQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsluJUdWxroNnyMMSMh3psw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsluJUdWxroNnyMMSMh3psw.png" alt="Book of Nodes" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your code, let’s randomize our light’s color every time the timer times out (every second).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var directional_light_2d = $DirectionalLight2D

func _on_timer_timeout():
 directional_light_2d.color = Color(randf(), randf(), randf()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and enjoy the overstimulation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F744%2F1%2Aab-ghjK0vwX38r7NlGLz8g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F744%2F1%2Aab-ghjK0vwX38r7NlGLz8g.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  PointLight2D
&lt;/h1&gt;

&lt;p&gt;The PointLight2D node emits light in all directions from a single point. This type of light is useful for creating focused lighting effects, such as flashlights, lamps, or fires.&lt;/p&gt;

&lt;p&gt;This node’s two main properties are the energy , color, texture scale, and textureproperties. The energy property determines how bright/dim the light is. The color is the shading of the light. The textureproperty allows us to give our light a shape. The texture scale property determines the size of our light.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASen7JrZNvyYuo_XeybakIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASen7JrZNvyYuo_XeybakIQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a flickering torch.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In your scene, add a PointLight2D node. We’ll need to give it a shape, so download &lt;a href="https://opengameart.org/content/flashlight-pattern-incandescent" rel="noopener noreferrer"&gt;this&lt;/a&gt; texture, and drag it into your texture property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFiZc6ArlRaxmevW1z2yrlw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFiZc6ArlRaxmevW1z2yrlw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play around with the energy, color, andtexture scalevalues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArsjpxyDC3LqL13YNqGI3lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArsjpxyDC3LqL13YNqGI3lg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just for fun, let’s give it a flicker effect. We’ll do this via an AnimationPlayer node.&lt;/li&gt;
&lt;li&gt;Create a new animation in the AnimationPlayer.&lt;/li&gt;
&lt;li&gt;Add a track for the energy property of the PointLight2D.&lt;/li&gt;
&lt;li&gt;Add keyframes to the energy track to simulate flickering.&lt;/li&gt;
&lt;li&gt;Enable looping, and change the blend mode to discrete.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F411%2F1%2ANBaODpcdb9Oln4jng2L8IQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F411%2F1%2ANBaODpcdb9Oln4jng2L8IQ.png" alt="Book of Nodes" width="411" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F898%2F1%2Awlllqgb0xLjPrkV-o2XJUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F898%2F1%2Awlllqgb0xLjPrkV-o2XJUw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APIaS1p0e2T3Ym77tcE6CRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APIaS1p0e2T3Ym77tcE6CRQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU6IOwPK4JqZF7hA2QqstWQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU6IOwPK4JqZF7hA2QqstWQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Atvbaz9YCIxm1hzVOj4kLkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Atvbaz9YCIxm1hzVOj4kLkw.png" alt="Book of Nodes" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2AnYwmUr6mKA6zRTrQfQg_fw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2AnYwmUr6mKA6zRTrQfQg_fw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then play this animation via the code when the game loads.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var animation_player = $AnimationPlayer

func _ready():
 animation_player.play("flicker")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and observe the player’s color changes when they go into the flickering lights.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F636%2F1%2ArejV_mnlCSCW8fD0_lJgCQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F636%2F1%2ArejV_mnlCSCW8fD0_lJgCQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  LightOccluder2D
&lt;/h1&gt;

&lt;p&gt;The LightOccluder2D node is used to cast shadows from a light source that hits it. This light source can come from a DirectionalLight2D or PointLight2D. It requires an OccluderPolygon2D to define the shape of the occlusion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASen7JrZNvyYuo_XeybakIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASen7JrZNvyYuo_XeybakIQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Cast a shadow from our player.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a LightOccluder2D node to the source you want to cast your shadows from.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F874%2F1%2Aw0QcJvpXBv5CkI_23hQdHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F874%2F1%2Aw0QcJvpXBv5CkI_23hQdHg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see it has an error. This is because we need to draw a OccluderPolygon2D shape to define the shape of our shadow. Give your LightOccluder2D a new OccluderPolygon2D resource, and draw the polygon around your player. Make sure that you &lt;strong&gt;complete&lt;/strong&gt; your polygon by connecting all of your points.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F580%2F1%2AWxybCnJuoAAnK17QSnJV5A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F580%2F1%2AWxybCnJuoAAnK17QSnJV5A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwmKh-ER7cz1cKGbEvdG7uQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwmKh-ER7cz1cKGbEvdG7uQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now in our Main scene, we will need a light source to cast this shadow shape. Let’s add a PointLight2D node and put it above our player. Make sure its shadows are enabled so that it can cast this shadow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWSYXqhnI2JAUlLkNsUMpFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWSYXqhnI2JAUlLkNsUMpFw.png" alt="Book of Nodes" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene and watch the shadow move depending on where the light hits the occluder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F442%2F1%2ADobKUc5hrIC5RRcr-0vpvA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F442%2F1%2ADobKUc5hrIC5RRcr-0vpvA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AudioStreamPlayer2D and AudioStreamPlayer
&lt;/h1&gt;

&lt;p&gt;These nodes are used to play audio in our games. We use the AudioStreamPlayer to play audio equally across our scene (such as background music or ambient sounds), and the AudioStreamPlayer2D to play audio positionally (such as from our players or NPCs).&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Play ambient music in the background, and sounds from the player when they move.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Download your sound effects. You can find free ones on &lt;a href="https://pixabay.com/sound-effects/search/game/" rel="noopener noreferrer"&gt;Pixabay&lt;/a&gt;. Look for ones that work well in the background (they loop), and ones that are short effects, such as jumping sounds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aow1d7YpvsSWPYqah-Stg5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aow1d7YpvsSWPYqah-Stg5w.png" alt="Book of Nodes" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AiCzB9Df3lRp71foRVuc8Ww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AiCzB9Df3lRp71foRVuc8Ww.png" alt="Book of Nodes" width="800" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an AudioStreamPlayer node to play background audio. Add an AudioStreamPlayer2D node to play positional audio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F403%2F1%2AC1yHiRg_JkPvloXo-hRdZQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F403%2F1%2AC1yHiRg_JkPvloXo-hRdZQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will need to reimport your audio that is supposed to loop. Double-click it, and enable looping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F732%2F1%2AfznPUW2tCpy9aqxI9XeGsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F732%2F1%2AfznPUW2tCpy9aqxI9XeGsg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the stream property to the desired audio file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F573%2F1%2AlF6ZSKfDoI6NezPU-FjnlQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F573%2F1%2AlF6ZSKfDoI6NezPU-FjnlQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F570%2F1%2AS1QD7YUU0Mqwj3raZNOvAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F570%2F1%2AS1QD7YUU0Mqwj3raZNOvAQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust properties like volume_db, and pitch_scale if needed. We’ll enable autoplay on our AudioStreamPlayer node since that is our background music.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F575%2F1%2Ayxwvs01ZT6APelQ1_7KyTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F575%2F1%2Ayxwvs01ZT6APelQ1_7KyTg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will play our sound effect audio (AudioStreamPlayer2D) when our player enters a certain area. To do this, add an Area2D node to your scene with a collision body, and attach its on_body_entered() signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F853%2F1%2A9zGfWUIaRtWBy2aIdvZVJw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F853%2F1%2A9zGfWUIaRtWBy2aIdvZVJw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F993%2F1%2Ag6ZgN_6D38JRvptEgJGR4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F993%2F1%2Ag6ZgN_6D38JRvptEgJGR4A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now play the audio when the player enters the area.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var audio_stream_player_2d = $AudioStreamPlayer2D

func _on_area_2d_body_entered(body):
 if body.name == "Player":
  audio_stream_player_2d.play()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene. The background music should play, and the sound effect should play when your player enters the area.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  NavigationAgent2D, NavigationObstacle2D, NavigationRegion2D
&lt;/h1&gt;

&lt;p&gt;The NavigationAgent, NavigationObstacle, and NavigationRegion nodes are used to manage navigation and pathfinding in both 2D and 3D environments. These nodes help create dynamic and realistic movement for characters and objects, allowing them to navigate around obstacles and follow paths.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The NavigationAgent2Dnode is used to move characters along a path while avoiding obstacles.&lt;/li&gt;
&lt;li&gt;The NavigationObstacle2Dnode is used to create obstacles that navigation agents will avoid.&lt;/li&gt;
&lt;li&gt;The NavigationRegion2D node defines areas where navigation is allowed or restricted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0iZy9Ub05IbpDC6JYms-nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0iZy9Ub05IbpDC6JYms-nw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These three nodes combined allow us to create a more immersive world through mechanics such as NPC and Enemy roaming, particle movements, and controlled entity spawning.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create an NPC that roams around a certain area on the map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In your Main scene, add a NavigationRegion2D to your scene to define the roaming area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F390%2F1%2Ayp7KpIBIsvP5MfvYJ-gB7A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F390%2F1%2Ayp7KpIBIsvP5MfvYJ-gB7A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new NavigationPolygonresource for this node so that we can define our region. Draw the polygon to where you want your region to be.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F561%2F1%2AKMqWNcvHRzVp-SJYxaqrqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F561%2F1%2AKMqWNcvHRzVp-SJYxaqrqw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F913%2F1%2Azlg2HjgBbu9z6pDfAo5DYg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F913%2F1%2Azlg2HjgBbu9z6pDfAo5DYg.png" alt="Book of Nodes" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now all we need to do is select our NavigationRegion node and select &lt;strong&gt;“Bake Navigation”&lt;/strong&gt;. You’ll see a blue-colored polygon get drawn over our floor, that is our navigation region!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsBmZK2iOiEcO16ZcBn82FQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsBmZK2iOiEcO16ZcBn82FQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a new scene, create your NPC using a CharacterBody2Dnode as the root node. Add the collisions and animations for this entity just as you did for your player.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1020%2F1%2AdJP2LVIYutrJ4bBiJXbSwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1020%2F1%2AdJP2LVIYutrJ4bBiJXbSwA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To your NPC scene, add a NavigationAgent2D node. The NPC will be assigned to this agent so that they can roam in the region. Enable avoidance for this NPC so that they can avoid obstacles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F391%2F1%2AMgjO19Lyqwe-VdASGmOCQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F391%2F1%2AMgjO19Lyqwe-VdASGmOCQg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F590%2F1%2AS3Kk9yRJyf_nmvl14tlHnA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F590%2F1%2AS3Kk9yRJyf_nmvl14tlHnA.png" alt="Book of Nodes" width="590" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach a script to your NPC. We will then need to connect our signals from our NavigationAgent2D node to &lt;strong&gt;1)&lt;/strong&gt; compute the avoidance velocity of our NPC, and &lt;strong&gt;2)&lt;/strong&gt; redirect our NPC when that target is reached. For moving the NPC whilst avoiding obstacles, attach the velocity_computed signal to your script. For redirecting the NPC, attach the navigation_finished signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1005%2F1%2Aq_jhTHCoSCxSLQMQZhpcFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1005%2F1%2Aq_jhTHCoSCxSLQMQZhpcFw.png" alt="Book of Nodes" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1023%2F1%2AFvlT3Sf1LO0k7LeKlLz_Og.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1023%2F1%2AFvlT3Sf1LO0k7LeKlLz_Og.png" alt="Book of Nodes" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We also want our NPC to pause before redirecting. To do this, we will add a Timer node to our scene. Enable its one_shot property, and change its wait_time to however long you want the NPC to wait before roaming again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F398%2F1%2Am_D-IJ2yg3846gPk761pCQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F398%2F1%2Am_D-IJ2yg3846gPk761pCQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F602%2F1%2ARbWFyCQ6VXiN-PkCur2aOg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F602%2F1%2ARbWFyCQ6VXiN-PkCur2aOg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also attach its timeout() signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F992%2F1%2AIw8JnzGohrg9KzVM6raHTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F992%2F1%2AIw8JnzGohrg9KzVM6raHTg.png" alt="Book of Nodes" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now add your roaming functionality.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### NPC.gd

extends CharacterBody2D

@onready var navigation_agent_2d = $NavigationAgent2D
@onready var navigation_region = $"../NavigationRegion2D"
@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var timer = $Timer

# Variables
@export var movement_speed: float = 50.0
var roaming_area: Rect2 
var target_position: Vector2  

func _ready():
 # Add a delay to ensure the navigation map is loaded
 await get_tree().create_timer(1).timeout
 set_roaming_area()
 set_random_target()

func _physics_process(delta):
 # Move NPC towards the target
 var next_path_position = navigation_agent_2d.get_next_path_position()
 var new_velocity = (next_path_position - global_position).normalized() * movement_speed
 if navigation_agent_2d.avoidance_enabled:
  navigation_agent_2d.velocity = new_velocity
 else: 
  _on_navigation_agent_2d_velocity_computed(new_velocity)

 # Update the NPC's position
 move_and_slide()

 # Play walking animation
 update_animation(velocity)

func set_roaming_area():
 # Set the roaming area
 var navigation_polygon = navigation_region.get_navigation_polygon()
 if navigation_polygon.get_outline_count() &amp;gt; 0:
  var outline = navigation_polygon.get_outline(0)
  # Calculate the bounding rect
  var min_x = INF
  var min_y = INF
  var max_x = -INF
  var max_y = -INF
  for point in outline:
   min_x = min(min_x, point.x)
   min_y = min(min_y, point.y)
   max_x = max(max_x, point.x)
   max_y = max(max_y, point.y)
  roaming_area = Rect2(min_x, min_y, max_x - min_x, max_y - min_y)
 else:
  print("No outlines found in the navigation polygon.")

func set_random_target():
 # Set next roaming position within the roaming area
 target_position = Vector2(
  randf_range(roaming_area.position.x, roaming_area.position.x + roaming_area.size.x),
  randf_range(roaming_area.position.y, roaming_area.position.y + roaming_area.size.y)
 )
 navigation_agent_2d.set_target_position(target_position)

func update_animation(velocity: Vector2):
 if velocity.length() == 0:
  animation_state.travel("idle")
 else:
  animation_state.travel("walk")
  animation_tree.set("parameters/walk/blend_position", velocity.normalized())

func _on_navigation_agent_2d_velocity_computed(safe_velocity):
 # Move NPC
 velocity = safe_velocity

func _on_timer_timeout():
 # Move NPC again
 set_random_target()

func _on_navigation_agent_2d_navigation_finished():
 # When path reached, redirect NPC
 velocity = Vector2.ZERO
 animation_state.travel("idle")
 timer.start()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Instance your NPC in your Main scene. Move them into your region.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwTwiwb5RvGsLAXcSUSDWkQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwTwiwb5RvGsLAXcSUSDWkQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optionally, add NavigationObstacle2D nodes to create obstacles. Add this node to a StaticBody2D with a collision shape.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkV3KZK_-NjZw5IR2l1swWQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkV3KZK_-NjZw5IR2l1swWQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AH_s0ZnKm32p39GsrbK_exQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AH_s0ZnKm32p39GsrbK_exQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene and see your NPC randomly roam. They should avoid your obstacles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F620%2F1%2At6ouFhF1ssypSce7jgXBSw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F620%2F1%2At6ouFhF1ssypSce7jgXBSw.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Path2D and PathFollow2D
&lt;/h1&gt;

&lt;p&gt;The Path2D and PathFollow2D nodes work together to create and follow paths in a 2D space. The Path2D node is used to define a path using a sequence of points. I like this more than using a NavMesh because it allows you to create and visualize a path in the Godot editor, instead of randomizing it. The PathFollow2D node is used to make an object follow a path defined by a Path2D node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARCM31wIPKpff6QlV5OIs8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARCM31wIPKpff6QlV5OIs8g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create an NPC that roams on a defined path on the map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Path2D node in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F396%2F1%2A3k8EcosQwS9UT2s3pIzK0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F396%2F1%2A3k8EcosQwS9UT2s3pIzK0g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a PathFollow2D node as a child of the Path2D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F406%2F1%2AZuNkK5IjLu2Xl-7PjeDDcA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F406%2F1%2AZuNkK5IjLu2Xl-7PjeDDcA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the rotatesvalue of this path is disabled since our NPC should only move diagonally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F329%2F1%2ANwJhPcDQnp0iv5LLrmwM4Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F329%2F1%2ANwJhPcDQnp0iv5LLrmwM4Q.png" alt="Book of Nodes" width="329" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a new scene, create your NPC using a CharacterBody2Dnode as the root node. Add the collisions and animations for this entity just as you did for your player.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1020%2F1%2AdJP2LVIYutrJ4bBiJXbSwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1020%2F1%2AdJP2LVIYutrJ4bBiJXbSwA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach your NPC to your PathFollow2D node. This will tell the game that this is the object that should follow this Path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F393%2F1%2A6C7odgtvDK_Zh7Ps0DRTpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F393%2F1%2A6C7odgtvDK_Zh7Ps0DRTpw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can draw our path. In the Godot editor, select the Path2D node. Use the “Add Point” button in the toolbar to add points to draw the path shape that your NPC has to follow. Select the point to move it on your map.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2AyWwcqCO3dyx9BNSD5t3S5A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2AyWwcqCO3dyx9BNSD5t3S5A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_Crd79ge2nj3u-Tt4_aLAg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_Crd79ge2nj3u-Tt4_aLAg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F327%2F1%2AXs5TOY5e3ySBcbaqV-E9DQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F327%2F1%2AXs5TOY5e3ySBcbaqV-E9DQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add more points to complete your path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ab9KuHvMSLXxqO2A8HMbyLA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ab9KuHvMSLXxqO2A8HMbyLA.png" alt="Book of Nodes" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F331%2F1%2Aw6o6-Xg0t6Lsk2nTAZs53Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F331%2F1%2Aw6o6-Xg0t6Lsk2nTAZs53Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With your path created, attach a script to your NPC. Then, add the logic for them to move along the path.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### NPC.gd

extends CharacterBody2D

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var path_follow = get_parent()

# Variables
@export var speed = 50.0
var current_offset = 0.0
var path_length = 0.0
var direction = 1

func _ready():
 # Get the total length of the path
 path_length = path_follow.get_parent().curve.get_baked_length()

func _physics_process(delta):
 # Update the progress along the path
 update_path_progress(delta)
 update_animation(Vector2(direction, 0))
 move_and_slide()

func update_path_progress(delta):
 # Update the progress along the path
 current_offset += speed * delta * direction
    # Reverse direction if the end or start of the path is reached
 if current_offset &amp;gt;= path_length or current_offset &amp;lt;= 0:
  direction *= -1 
 current_offset = clamp(current_offset, 0, path_length)
 path_follow.progress = current_offset

func update_animation(velocity: Vector2):
 if velocity.length() == 0:
  animation_state.travel("idle")
 else:
  animation_state.travel("walk")
  animation_tree.set("parameters/walk/blend_position", velocity.normalized())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and see your NPC roam. They should follow your path in a zig-zag (back-and-forth) motion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F644%2F1%2AGZd6a25VmFGURSeRb2CBnw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F644%2F1%2AGZd6a25VmFGURSeRb2CBnw.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  TileMap
&lt;/h1&gt;

&lt;p&gt;The TileMap node allows us to create 2D grid-based levels. With it, we can place our objects directly onto a grid to draw our world.&lt;/p&gt;

&lt;p&gt;The TileMap is composed of cells. Each cell has the same dimensions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvI-UbEn07LnMtMO3_9s9Ug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvI-UbEn07LnMtMO3_9s9Ug.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The TileMap uses a TileSet Resource that contains an array of 2D tiles that can be placed on cells on the grid. Each tile is comprised of a sprite, either from an atlas (tilesheet) or an individual image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARZDgs9K4ooGu2d-8PwfszA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARZDgs9K4ooGu2d-8PwfszA.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also add these tiles on different layers, which are added on top of other objects on the grid. These tiles can also have their own collision, navigation, and physics properties.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A25CdEMaQg8wLqeR01a4fRg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A25CdEMaQg8wLqeR01a4fRg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANrGJU-TBqrmFShRY3axNng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANrGJU-TBqrmFShRY3axNng.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AnpwhY-DebZ_VOCg2YcX3RQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AnpwhY-DebZ_VOCg2YcX3RQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my 2D base template project, you will see that my entire (very basic) world was made using several layers and tilesheets on the TileMap node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AyVcX0aVHASQo_7lsh6z4pw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AyVcX0aVHASQo_7lsh6z4pw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a tile-based map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Let’s start by adding a TileMap node to our scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F392%2F1%2ANOt02o0fZBCS8Xa1EpHBFA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F392%2F1%2ANOt02o0fZBCS8Xa1EpHBFA.png" alt="Book of Nodes" width="392" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Inspector Panel, give this node a new TileSet resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F338%2F1%2AYiH0bfKHgz9uGlEyfi4-VQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F338%2F1%2AYiH0bfKHgz9uGlEyfi4-VQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see a panel open at the bottom. This is where we can add the sprites and tilesheets that we want to draw on our TileMap. To make it clear, we &lt;strong&gt;create&lt;/strong&gt; tiles in the TileSet panel, and we &lt;strong&gt;draw&lt;/strong&gt; these tiles onto our world in the TileMap panel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Azg7LZTCrvZ8GwaIoxwgU1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Azg7LZTCrvZ8GwaIoxwgU1g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, find a tilesheet or a sprite that you like, and drag it into this panel. Say yes to the prompt if you are using a tilesheet so that it can separate the tiles into grid cells.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtxQwQQp9as4KoWXEBQhXgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtxQwQQp9as4KoWXEBQhXgw.png" alt="Book of Nodes" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwejCCAWmDElEZw4kv8lXXw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwejCCAWmDElEZw4kv8lXXw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here we can give our tileset a name and change its margins (if necessary, usually it’s not).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3FXYbzH2l5JJbNFw1VWXsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3FXYbzH2l5JJbNFw1VWXsw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Select and Paint panels, we can draw properties such as navigation, collision, or other physics properties onto our tiles. We’ll get to that in a bit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7yHnX-E9UqEa5fYVpUZXxA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7yHnX-E9UqEa5fYVpUZXxA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AeU5loYGqmG70Uh2ygWYGGw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AeU5loYGqmG70Uh2ygWYGGw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, go to your TileMap panel. You will see that we can paint our tiles onto our screen. Using the tools, you can draw, erase, or select tiles that you have added.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F463%2F1%2AnNQnKZaqBYkon1K2TbD-hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F463%2F1%2AnNQnKZaqBYkon1K2TbD-hw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APwnoyJo8qFGj4ThFZKgiCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APwnoyJo8qFGj4ThFZKgiCg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can also erase tiles by hovering over them and holding down your &lt;strong&gt;right&lt;/strong&gt; mouse button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F387%2F1%2AQ2R8AIVTXywfU0flrDHjrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F387%2F1%2AQ2R8AIVTXywfU0flrDHjrw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can rotate tiles via the X and Z keys on your keyboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F328%2F1%2A7tBfXcy7Je14f0a5tKUtcQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F328%2F1%2A7tBfXcy7Je14f0a5tKUtcQ.png" alt="Book of Nodes" width="328" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F519%2F1%2AgNV-WTBhkvN-GdPTIcOCxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F519%2F1%2AgNV-WTBhkvN-GdPTIcOCxw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see that we are drawing all the tiles on one layer. If you draw a tile over an existing one, it will replace that tile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F332%2F1%2AN64Zwh1cmDHnEmOYoHN-cA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F332%2F1%2AN64Zwh1cmDHnEmOYoHN-cA.png" alt="Book of Nodes" width="332" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F207%2F1%2ApHC_0s_y2hKu-pcBFtrnEw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F207%2F1%2ApHC_0s_y2hKu-pcBFtrnEw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F189%2F1%2A34IiKhUeKs1q6Ou_sWfieg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F189%2F1%2A34IiKhUeKs1q6Ou_sWfieg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We don’t want this, so let’s add more layers. In the Inspector Panel, underneath Layers, press the “Add Element” button to add more layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F657%2F1%2AZe7e9cOm20smSm0ZIII-kw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F657%2F1%2AZe7e9cOm20smSm0ZIII-kw.png" alt="Book of Nodes" width="657" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F264%2F1%2AKBlLipl1qRH2zvYhX4mQMw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F264%2F1%2AKBlLipl1qRH2zvYhX4mQMw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can draw on our different layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2A9sMAl2o6OWgBYhZD6fzwGg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2A9sMAl2o6OWgBYhZD6fzwGg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F362%2F1%2AM6QNHS5GxNz-DU3qlOhbeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F362%2F1%2AM6QNHS5GxNz-DU3qlOhbeA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F316%2F1%2AeqxPmmTTsXW69bFcvHtFPg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F316%2F1%2AeqxPmmTTsXW69bFcvHtFPg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;But what about collisions? For this, we need a Physics Layer. Click on the TileSet resource in your Inspector Panel, and navigate to Physics Layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F655%2F1%2A1WwwUSvc8Crjd5u5456BdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F655%2F1%2A1WwwUSvc8Crjd5u5456BdA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click “Add Element” to add a layer. You usually only need one layer for collisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F635%2F1%2AWo2XNfmkoLGJUwuej184HQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F635%2F1%2AWo2XNfmkoLGJUwuej184HQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now go back to your TileSet panel, and navigate to the Paint pane. Select the Physics property, and select the layer you just created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A47It8H8gy6wAkbE2XL_DPA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A47It8H8gy6wAkbE2XL_DPA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F851%2F1%2AnSnSdwvX3zdpuyCTlEIJnA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F851%2F1%2AnSnSdwvX3zdpuyCTlEIJnA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can draw collisions wherever we want the player and other entities to be blocked. We usually only do this on objects such as trees, buildings, or the outer boundaries of our map.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGBxB0oM36A-l9cufc4M0Jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGBxB0oM36A-l9cufc4M0Jg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_dAl0IYNEv4WL3ZDJJ5IiQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_dAl0IYNEv4WL3ZDJJ5IiQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To delete collisions, just clear your polygon on the left and click on your existing cells.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6-oeK-dDB-_yMGWgMdxhcQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6-oeK-dDB-_yMGWgMdxhcQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can add more tilesheets and draw collisions on there too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APOs0zFva1B4Jx8b0No6sVg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APOs0zFva1B4Jx8b0No6sVg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The last thing I want to show you is autotiling. Drawing the ground tile for tile, with all of its edges is extremely tedious. We can make use of autotiling, also called TERRAINS, to speed up this process. This feature automatically selects and places the appropriate tile based on the surrounding tiles, ensuring that the tiles blend seamlessly together.&lt;/li&gt;
&lt;li&gt;Click on the TileSet resource in your Inspector Panel, and navigate to Terrain Sets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F654%2F1%2A3LjE3QszMoPcQRU_qwOV6Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F654%2F1%2A3LjE3QszMoPcQRU_qwOV6Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will add an Element for each resource we want to “autotile”. So if you added a tilesheet for dirt, grass, water, and mud in your TileSet panel, you will create an element for each of those resources. Since we only have the “Dirt” tilesheet (we don’t want to autotile foliage or buildings), we will only add one element.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F646%2F1%2AP9KFl_rZJowPG_a536HGmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F646%2F1%2AP9KFl_rZJowPG_a536HGmw.png" alt="Book of Nodes" width="646" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F643%2F1%2AHujUpZe_4I9Jb3QkOs6QAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F643%2F1%2AHujUpZe_4I9Jb3QkOs6QAA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F640%2F1%2AG0xOBa-nlL8nKKtFwQrAMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F640%2F1%2AG0xOBa-nlL8nKKtFwQrAMg.png" alt="Book of Nodes" width="640" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If we had a “Grass” TileSet, we would add another element.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F643%2F1%2Awo5fqJwetweWZXuHAHAu9Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F643%2F1%2Awo5fqJwetweWZXuHAHAu9Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now go back to your TileSet panel, and navigate to the Paint pane. Select the Terrains property, and select the layer you just created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F960%2F1%2A9r4aW8t1ea6EBm1Tid4sOQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F960%2F1%2A9r4aW8t1ea6EBm1Tid4sOQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F836%2F1%2A4Vk1_25Rtc_SLQsdFkIQVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F836%2F1%2A4Vk1_25Rtc_SLQsdFkIQVQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F499%2F1%2AVZPylSE-fjOYaPWfgt-luQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F499%2F1%2AVZPylSE-fjOYaPWfgt-luQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we will draw in our bits. This is what the engine will use to check the tiles for the appropriate variant to use. This might be confusing to you, but just remember to select all the areas of your tilemap that ARE NOT on weird shapes or corners.&lt;/li&gt;
&lt;li&gt;You will have to play around with the tiles to find the bits that give you the best results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AExV4A0H_20FWYx9V6WZ_HQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AExV4A0H_20FWYx9V6WZ_HQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate back to your TileMap node, and go to the terrains property. You’ll see that your autotiles have been created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASarDY7OSGX4lb0UoO8xO4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASarDY7OSGX4lb0UoO8xO4A.png" alt="Book of Nodes" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select your terrain and draw it onto the screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F508%2F1%2AadjED_d-DWLLi1kaIK2cdg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F508%2F1%2AadjED_d-DWLLi1kaIK2cdg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go ahead and create your mini world. You can also select and drag commonly used tiles into the Patterns panel for easy access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F882%2F1%2ABj4eYLq5E0ROYE-RqfVaCQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F882%2F1%2ABj4eYLq5E0ROYE-RqfVaCQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F997%2F1%2A-grGISF9vmFW5R0fcufcTw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F997%2F1%2A-grGISF9vmFW5R0fcufcTw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7bzBd-ifQFjCkm7HGPfoqQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7bzBd-ifQFjCkm7HGPfoqQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene and test your creation!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4GXoOFLBZaT0J6XjTBpSsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4GXoOFLBZaT0J6XjTBpSsg.png" alt="Book of Nodes" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Timer
&lt;/h1&gt;

&lt;p&gt;The Timer node is used to create countdown timers that can trigger events after a specified period. The Timer node provides several properties to control its behavior, including wait_time, autostart, and one_shot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;wait_time&lt;/strong&gt; : The duration in seconds that the timer will count down before emitting the timeout signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;autostart&lt;/strong&gt; : If set to true, the timer will start automatically when the scene is loaded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;one_shot&lt;/strong&gt; : If set to true, the timer will stop after emitting the timeout signal once. If false, the timer will restart automatically after each timeout.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It comes with a timeout signal, which is emitted when the timer reaches zero. This signal can be connected to a function to perform specific actions when the timer completes its countdown. The timeout signal is a crucial part of the Timer node's functionality, allowing you to trigger events at precise intervals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Spawn an enemy every 5 seconds.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Timer node to your scene. Set its wait_time to 5 seconds. Since we want the enemy to “spawn” as soon as the game loads, we should enable its autostart property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F332%2F1%2ASew9B01J9QxlwvT0gTo54A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F332%2F1%2ASew9B01J9QxlwvT0gTo54A.png" alt="Book of Nodes" width="332" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F501%2F1%2AdRQl052lJst_pl0nbWwPxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F501%2F1%2AdRQl052lJst_pl0nbWwPxQ.png" alt="Book of Nodes" width="501" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect the timer node’s timeout signal to your script. This will execute our logic to spawn our enemy every 5 seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F768%2F1%2AIIzpINBLUta2LuLxCaSSNQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F768%2F1%2AIIzpINBLUta2LuLxCaSSNQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your code, let’s “spawn” an enemy. Since we don’t have an actual enemy scene, we will just print the amount of enemies we have spawned.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node2D

@onready var timer = $Timer
var enemy_count = 0

func _ready():
 if not timer.is_stopped():
  timer.start()

func _on_timer_timeout():
 spawn_enemy()

func spawn_enemy():
 enemy_count += 1
 print("An enemy has spawned!")
 print("Current enemy count: ", enemy_count)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your game and your enemy should spawn each time the timer reaches 0!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aswh8PGWB5nOLpGF765Pd_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aswh8PGWB5nOLpGF765Pd_w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>godot</category>
      <category>2d</category>
      <category>guid</category>
    </item>
    <item>
      <title>The Book of Nodes: 3D</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Wed, 07 Aug 2024 12:44:24 +0000</pubDate>
      <link>https://forem.com/christinec_dev/the-book-of-nodes-3d-3f9n</link>
      <guid>https://forem.com/christinec_dev/the-book-of-nodes-3d-3f9n</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below you can find a list of 3D nodes that can be used in Godot 4. This is part of my &lt;a href="https://dev.to/christinec_dev/the-book-of-nodes-1p9c"&gt;Book of Nodes&lt;/a&gt; series. If you want to see similar content on 2D or UI nodes, please refer to the parent page of this post for those links. 😊&lt;/p&gt;

&lt;p&gt;Before we begin, if you need a base project to test these code snippets, feel free to download my FREE 2D and 3D templates &lt;a href="https://christinecdevs.site/2d-3d-prototype-templates/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I’ll be using these templates throughout this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*Please note that this list is not 100% complete yet, but I will be updating this list as time goes on.&lt;/em&gt;&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AnimatedSprite3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AnimationPlayer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AnimationTree&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Area3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AudioStreamPlayer3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skeleton3D, Bone3D, and BoneAttachment3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Camera3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CharacterBody3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CollisionShape3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DirectionalLight3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GridMap&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MeshInstance3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NavigationAgent3D, NavigationObstacle3D, NavigationRegion3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OmniLight3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Path3D, PathFollow3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RayCast3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RigidBody3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sprite3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spotlight3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StaticBody3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VehicleBody3D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WorldEnvironment&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Node3D
&lt;/h1&gt;

&lt;p&gt;The Node3Dnode is the fundamental building block for all 3D scenes in Godot. It is the base node for all 3D-related functionalities, providing 3D spatial features like position, rotation, and scale. Almost all 3D nodes (like CharacterBody3D, Area3D, etc.) inherit from Node3D, which makes it the core of any 3D scene structure in Godot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ay6bTwrwmvUgkKXGk19PWeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ay6bTwrwmvUgkKXGk19PWeQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Rotate a group of 3D nodes collectively.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Node3D to your scene to serve as a parent node. In an actual project, this could be used to represent a complex object like a spacecraft or a robot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F356%2F1%2AxuQz3w-k3w9DmeaO9XIn3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F356%2F1%2AxuQz3w-k3w9DmeaO9XIn3w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add child nodes such as twoMeshInstance3Dnodes. These children can represent visual components, collision areas, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2AHNAe64mFCZRptRbhGXALcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2AHNAe64mFCZRptRbhGXALcw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give the MeshInstance3Dnodes a shape of your choosing. I’m going to choose a BoxMeshshape.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQTPF8kH6dyUzrsV5_XapXg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQTPF8kH6dyUzrsV5_XapXg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now if we manipulate the Node3D parent, it will affect all its children. For example, rotating the Node3D will rotate all its children, whilst maintaining their relative positions and transformations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F588%2F1%2Ag2VshRO1sMhL6xy8yeWTZA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F588%2F1%2Ag2VshRO1sMhL6xy8yeWTZA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can also do this via code — say every second the game runs the node should rotate around the y-axis pivot point.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

@onready var node_3d = $Node3D

func _process(delta):
    node_3d.rotate_y(1.0 * delta) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F624%2F1%2AWQrsbWY_O7ZcLihyvX3h0w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F624%2F1%2AWQrsbWY_O7ZcLihyvX3h0w.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  MeshInstance3D
&lt;/h1&gt;

&lt;p&gt;The MeshInstance3D node in Godot is used to display 3D geometry. It takes a Meshresource and instances it in the current scene, which is essential for rendering 3D models.&lt;/p&gt;

&lt;p&gt;In Godot, a mesh is used as a resource that can be applied to MeshInstance3D nodes to render 3D geometry in a scene. Meshes in Godot can be created directly in the engine or imported from external 3D modeling tools such as Blender. Godot supports several 3D model formats for importing meshes, including .fbx, .gltf and .glb (glTF), .obj, and others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AJIqwKztu1MI7C5Vmgfw_UA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AJIqwKztu1MI7C5Vmgfw_UA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use this node to display characters, objects, or even simple shapes for prototyping, such as cylinders, planes, cubes, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A-r9RVsRag-vUiioIxlnqSw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A-r9RVsRag-vUiioIxlnqSw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Display a 3D model in a game scene.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Implementation:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a MeshInstance3D node within your 3D scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F368%2F1%2AqVHwkZmtmMs8y5Xzis1BgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F368%2F1%2AqVHwkZmtmMs8y5Xzis1BgQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Inspector, assign a mesh resource to the mesh property of the MeshInstance3D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F523%2F1%2ApLMhd943cAZW8nKcxJ-dPg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F523%2F1%2ApLMhd943cAZW8nKcxJ-dPg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqbumV0l6o4BYo6mTsCpeMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqbumV0l6o4BYo6mTsCpeMg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is great for prototyping, but what if you created a Mesh in Blender and want to show that instead of a shape? Well, you can drag your imported objects directly into your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F370%2F1%2AnRveqk8RUVBu9uOp2lsEYA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F370%2F1%2AnRveqk8RUVBu9uOp2lsEYA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFPmzs2doNxpDpOVbzmq81Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFPmzs2doNxpDpOVbzmq81Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1LdSoxV9PLArXwkVryoPZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1LdSoxV9PLArXwkVryoPZA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see that it is added to your scene underneath a Node3Dnode which has been imported as a scene. To access the MeshInstance3Dchild node from this parent, you’ll have to &lt;strong&gt;localize&lt;/strong&gt; the scene. Do this by right-clicking on the node, and selecting “Make Local”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F645%2F1%2AxEFy907EMWHlOuqasMsXwQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F645%2F1%2AxEFy907EMWHlOuqasMsXwQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvUWSCjPo20eBdKltZY8eSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvUWSCjPo20eBdKltZY8eSA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can now add collisions to this node, or even materials and shaders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACTbyFjIU3xOd9K2ofjBupw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACTbyFjIU3xOd9K2ofjBupw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxzPIVhnoheSTWqWRVBQydA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxzPIVhnoheSTWqWRVBQydA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1Dl9e9KVIT5TFj6sb-q5PQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1Dl9e9KVIT5TFj6sb-q5PQ.png" alt="Book of Nodes" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArQSURQwcMcn2kO2ojXoOoA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArQSURQwcMcn2kO2ojXoOoA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sprite3D
&lt;/h3&gt;

&lt;p&gt;The Sprite3D node in Godot is used to display 2D images in a 3D environment. This node can be set to always face the camera, which makes it useful for billboards, decals, NPC headlines, and other elements that need to be visible from all angles in a 3D space.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Mechanic:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Display a billboard that always faces the player.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Implementation:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Sprite3D node in your 3D scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFrC4dzgCZUjrxMCpBJ5Zcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFrC4dzgCZUjrxMCpBJ5Zcw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a texture to the texture property of the Sprite3D node in the Inspector. This texture will appear as a flat image in the 3D space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6F5emFEklP_Wjt_hSLercw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6F5emFEklP_Wjt_hSLercw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F986%2F1%2AEeY6vx7CAVIqbQ4A7rWLrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F986%2F1%2AEeY6vx7CAVIqbQ4A7rWLrg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AoLGDMrkZxh1z5jTAA7MRGA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AoLGDMrkZxh1z5jTAA7MRGA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Currently the image is just flat. To change this, enable the billboard_mode property of the Sprite3D to ensure it always faces the camera, making it visible from any angle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F511%2F1%2Ah60op2TlgsuPdsNDoMZclQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F511%2F1%2Ah60op2TlgsuPdsNDoMZclQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the scene and navigate around the 3D world to see the sprite always facing towards the camera, behaving like a billboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F596%2F1%2A9MsO690n_Vp7fKd-gHnxVg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F596%2F1%2A9MsO690n_Vp7fKd-gHnxVg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AnimatedSprite3D
&lt;/h1&gt;

&lt;p&gt;The AnimatedSprite3D node utilizes a series of images (sprites) and displays them in a sequence to create an animation in a 3D space. Unlike a simple Sprite3D node that displays a single static image in our world, AnimatedSprite3D can cycle through multiple frames to animate characters, objects, or effects within your 3D game. To create these frames, we can use either sprites or a spritesheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fproxy%2F0%2AIpsVa7TSEQJ1pO9T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fproxy%2F0%2AIpsVa7TSEQJ1pO9T.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AnimatedSprite3D node utilized the SpriteFrames Resource to create animations. This is a special resource in Godot that holds collections of images. Each collection can be configured as an animation by specifying the images (frames) that belong to it. You can create multiple animations within a single SpriteFrames resource, each with its own set of frames and playback properties like speed and loop settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcPJ28UYVB8fMfKCgUD2gCQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcPJ28UYVB8fMfKCgUD2gCQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ah85pYiiw0immlBhZ2odWKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ah85pYiiw0immlBhZ2odWKA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Animate a 3D spinning coin.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Download the &lt;a href="https://www.vecteezy.com/png/11947487-set-of-rotating-golden-and-silver-coins-set-of-spinning-gold-silver-coins-in-many-views-rotate-in-different-angles-isolated-on-white-background-3d-rendering" rel="noopener noreferrer"&gt;spinning coin sheet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create an AnimatedSprite3D node in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F359%2F1%2A3p-XY9B0y9qpR2jB7WzVSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F359%2F1%2A3p-XY9B0y9qpR2jB7WzVSA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a SpriteFrames resource to the AnimatedSprite3D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F486%2F1%2AEboip6FRUAq95o5DRQq4oQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F486%2F1%2AEboip6FRUAq95o5DRQq4oQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a new animation by clicking on the page+ icon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F258%2F0%2ArHjUExFn29eA6sJ0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F258%2F0%2ArHjUExFn29eA6sJ0.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rename this animation by double clicking on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F999%2F1%2A9qghTixfq4lq1O1tqpo_Rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F999%2F1%2A9qghTixfq4lq1O1tqpo_Rg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either drag in sprites into the frames box, or click the spritesheet icon to add animations via our coin atlas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1003%2F0%2Ay_k53LDhpemmP4R5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1003%2F0%2Ay_k53LDhpemmP4R5.png" alt="Book of Nodes" width="800" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crop out the frames horizontally and vertically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANXqXgNFwsmjJXZ9kZJWjcA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANXqXgNFwsmjJXZ9kZJWjcA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the frames you want. For instance, I will choose frame 0–4 in row 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2MUHc5ygj7Al2foVmQnpOQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2MUHc5ygj7Al2foVmQnpOQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale the coin down and move it to where you want it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlSkbSb_hAlhsBFguWPv1fQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlSkbSb_hAlhsBFguWPv1fQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then play the animation to see if you need to alter the FPS to make the coin rotate faster/slower.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F564%2F1%2AlwRQpQCOrGi5M-_tELa7pA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F564%2F1%2AlwRQpQCOrGi5M-_tELa7pA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also enable billboard settings so that our image retains its 3D look and feel (instead of looking like a flat 2D coin).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F510%2F1%2ADQJ-jyp-rR9vxmM8rIiBXg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F510%2F1%2ADQJ-jyp-rR9vxmM8rIiBXg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play the animation in your code so that when your player moves during runtime the animation can play:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

@onready var animated_sprite_3D = $AnimationSprite3D

func _ready():
    animated_sprite_3D.play("rotating_coin")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Start your project and observe the coin rotating around in your world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F346%2F1%2AAoh4dp3n6_uncE8q5bG9ZA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F346%2F1%2AAoh4dp3n6_uncE8q5bG9ZA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AnimationPlayer
&lt;/h1&gt;

&lt;p&gt;Unlike the AnimatedSprite3D which is specifically designed for image animations, the AnimationPlayer can animate virtually ANY node within a Godot scene. Instead of animating a simple sprite, you can animate the node’s properties — including but not limited to positions, rotations, scales, colors, and even variables.&lt;/p&gt;

&lt;p&gt;The AnimationPlayer can hold a set of animations on a singular timeline, each containing keyframes that define the start and end points of any property that changes over time. You can create complex sequences and control animations in a non-linear fashion.&lt;/p&gt;

&lt;p&gt;This node can be used to animate 2D, 3D, and even UI nodes!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Abn2akzwuRF3evvn2bCCZgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Abn2akzwuRF3evvn2bCCZgQ.png" alt="Book of Nodes" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvD9XpLTs_iyaRZ52jPB0rA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvD9XpLTs_iyaRZ52jPB0rA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a platform that moves up and down.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a MeshInstance3Dnode and an AnimationPlayernode to your scene. The MeshInstance3Dnode is the node we want to animate, and the property we want to animate of this node is its position.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F361%2F1%2AXete4O01viBPDCanXvxZoQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F361%2F1%2AXete4O01viBPDCanXvxZoQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a shape to the MeshInstance3Dnode. I’ll assign a simple box shape.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYtWlOQVg3qc4YK4kN-E8ug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYtWlOQVg3qc4YK4kN-E8ug.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change its scale to be more similar to a platform — Vector3(2, 0.2, 2).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvorpyBIY1XbPrk84CSFKDQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvorpyBIY1XbPrk84CSFKDQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the AnimationPlayer node.&lt;/li&gt;
&lt;li&gt;In the animation panel, click “New Animation” and name it something descriptive like “move_platform”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F341%2F1%2AOjbyCQuO6-GGtv9SvwgXaQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F341%2F1%2AOjbyCQuO6-GGtv9SvwgXaQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F994%2F1%2AdzX-H7vtol3wO4KBGsqaEg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F994%2F1%2AdzX-H7vtol3wO4KBGsqaEg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the animation length to the duration you want for one pulse cycle (e.g., 1 second).&lt;/li&gt;
&lt;li&gt;Enable the “Loop” option to make the animation repeat continuously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1002%2F1%2Ab6OuXK71qm2AfC9zFClWUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1002%2F1%2Ab6OuXK71qm2AfC9zFClWUw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the beginning of the animation timeline (0 seconds).&lt;/li&gt;
&lt;li&gt;Select the MeshInstance3D node, and in the Inspector, set the position property to its initial value (e.g., Vector3(0, 0, 0)).&lt;/li&gt;
&lt;li&gt;Right-click the position property in the Inspector and select "Key" to add a keyframe.&lt;/li&gt;
&lt;li&gt;Move to the middle of the timeline (e.g., 0.5 seconds), change the position to a larger value (e.g., Vector3(0, 1, 0)), and add another keyframe.&lt;/li&gt;
&lt;li&gt;At the end of the timeline (1 second), set the position back to the initial value (Vector3(0, 0, 0)) and add a final keyframe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F519%2F1%2A9mFI6YEOkknyJw_ZscNl-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F519%2F1%2A9mFI6YEOkknyJw_ZscNl-Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkQfBWmqORAN29PNEUCFSRA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkQfBWmqORAN29PNEUCFSRA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AXis4P4eWEadZuCDWDOxL9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AXis4P4eWEadZuCDWDOxL9A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAMIoPGrUldSRPu8lEPUotA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAMIoPGrUldSRPu8lEPUotA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can control when the animation starts or stops via script, or let it run continuously since it’s set to loop.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

@onready var animation_player = $AnimationPlayer
func _ready():
    animation_player.play("move_platform")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Start your project and observe the platform move up and down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F486%2F1%2A_0sDDSnZ8NLFjox7Je2RJQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F486%2F1%2A_0sDDSnZ8NLFjox7Je2RJQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AnimationTree
&lt;/h1&gt;

&lt;p&gt;The AnimationTree node enhances the capabilities of the AnimationPlayer by providing advanced features for animations, such as blending, transitions, and states. This makes it extremely easy to make detailed character animations and interactive scene elements in 2D and 3D environments.&lt;/p&gt;

&lt;p&gt;We usually use blending to create smooth transitions between animations, for example, smoothly transitioning between walking and running depending on the player’s speed.&lt;/p&gt;

&lt;p&gt;We use state machines to switch our animations dynamically depending on the conditions, for example, switching between idle and attack animations if the player presses a key.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Animate a 3D character with multiple actions (e.g., running, jumping, idle).&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add an AnimationPlayernode to your scene which has your 3D model, and create animations for it like "run", "attack", and "idle".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABMCh0zDoFXsiImNKTfkYEg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABMCh0zDoFXsiImNKTfkYEg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can also download animations from &lt;a href="https://www.mixamo.com" rel="noopener noreferrer"&gt;Mixamo&lt;/a&gt; if you don’t want to manually create these. If you want to download an animation from Mixamo, you will have to upload your 3D character (MAKE SURE IT’S THE SAME CHARACTER AS THE ONE IN YOUR GAME) to the dashboard, and then download the skin along with your desired animation.&lt;/li&gt;
&lt;li&gt;Then you’ll have to import the character with the animation into your project, add it to your scene, localize the scene, extract the animation (by saving it as a .res), and then you’ll have to load it into your original AnimationPlayer.&lt;/li&gt;
&lt;li&gt;Now, add an AnimationTree node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F352%2F1%2AjAtzqC589FB5E4k3yyJdZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F352%2F1%2AjAtzqC589FB5E4k3yyJdZA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure the tree_root as an AnimationRootNode for managing states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F433%2F1%2AxfII8nyCbbW-stIwR1O8nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F433%2F1%2AxfII8nyCbbW-stIwR1O8nw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also assign the AnimationPlayeras the Anim Player property because this is where our AnimationTree will call the animations from, and the Advanced Expression as the root node because this is where our animation coding can be found (our script).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F432%2F1%2Af2bwJhLPP7IeUzfQ3Jwdew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F432%2F1%2Af2bwJhLPP7IeUzfQ3Jwdew.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you open your AnimationTree, you will see if you right-click you can add animations, blend trees, and state machines. Add a new animation for ‘idle’, ‘walk’, ‘run’, and ‘jump’.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArzzKPz1nEYTnCByWwprpZQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArzzKPz1nEYTnCByWwprpZQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7Glli7kj8kbbNDbFWGlQmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7Glli7kj8kbbNDbFWGlQmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a transition between start -&amp;gt; idle. The transition type should be immediatebecause we want the animation to play immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F412%2F1%2A51amUda0gk3FaXVCC041hA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F412%2F1%2A51amUda0gk3FaXVCC041hA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add transitions between idle -&amp;gt; walk and vice versa. The transition type for both should be syncbecause we want to blend the animation. Also set the mode to enabledbecause we will activate this animation via the code, and not automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F496%2F1%2AJumBQJ4g5A2tIVG80UeVJQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F496%2F1%2AJumBQJ4g5A2tIVG80UeVJQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AajI0-vv_Q5VBXmYkK27cyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AajI0-vv_Q5VBXmYkK27cyA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select your transitions from walk &amp;lt;-&amp;gt; idle, and in the Inspector panel, change the x-fade time to a value such as 0.3. This is the blending time of the transitions, which smoothens out our transition from one animation to the next.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AzrljVaYpGsx7u9s36pkMFg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AzrljVaYpGsx7u9s36pkMFg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F588%2F1%2AYelr7EtfyG3Ij8uTL7f89g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F588%2F1%2AYelr7EtfyG3Ij8uTL7f89g.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do the exact same for the transitions between your walk &amp;lt;-&amp;gt; sprint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZsKEjibVzJzuim_qgxDFpQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZsKEjibVzJzuim_qgxDFpQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F560%2F1%2ARzlDcLB2nveNTmYF1YB6Cg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F560%2F1%2ARzlDcLB2nveNTmYF1YB6Cg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do the same for your jump animation, but it should transition back to all of your other animations (jump -&amp;gt; idle, jump -&amp;gt; walk, jump -&amp;gt; sprint). The transition from your Jump to other animations should be of type At End, because we want to transition back to running, walking, or jumping when the player has finished jumping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_HZSHOoJdpUHwXG9q_GOkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_HZSHOoJdpUHwXG9q_GOkw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, we only want to JUMP if our player is jumping by pressing the ui_jump key. For this we can make use if an expression. We can enter boolean values in the expressionpanel, which will then check our code for the conditions to play the animation based on this boolean. So, if in our code we say is_jumping = true when we press our jump button, this part of the AnimationTree will execute.&lt;/li&gt;
&lt;li&gt;Add an expression is_jumping to all of the transitions that go towards your jump animation (idle -&amp;gt; jump, walk -&amp;gt; jump, sprint -&amp;gt; jump).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AHT5hgBh_dbGPJJKciqDp-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AHT5hgBh_dbGPJJKciqDp-g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now in our code, we can play our animations.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody3D

# Vars
const run_speed = 3.0
const sprint_speed = 5.0
const jump_speed = 3.0
const gravity = 10

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var camera = $ThirdPersonCamera/Camera

var is_jumping = false

func _ready():
 Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _process(delta):
 handle_animation()

func _physics_process(delta):
 handle_movement(delta)

func handle_animation():
 var input_dir = Input.get_vector("ui_right", "ui_left", "ui_down", "ui_up")
 if is_jumping:
  if animation_state.get_current_node() != "jump":
   animation_state.travel("jump")
 elif input_dir.length() &amp;gt; 0:
  if Input.is_action_pressed("ui_sprint"):
   if animation_state.get_current_node() != "sprint":
    animation_state.travel("sprint")
  else:
   if animation_state.get_current_node() != "walk":
    animation_state.travel("walk")
 else:
  if animation_state.get_current_node() != "idle":
   animation_state.travel("idle")

func handle_movement(delta):
 # Check if the player has landed
 if is_on_floor() and velocity.y == 0:
  is_jumping = false
 # Apply gravity
 velocity.y += -gravity * delta

 # Get input direction
 var input_dir = Input.get_vector("ui_left", "ui_right", "ui_down", "ui_up")
 if input_dir.length() &amp;gt; 0:
  # Calculate movement direction based on camera orientation
  var forward = -camera.global_transform.basis.z
  var right = camera.global_transform.basis.x
  forward.y = 0  
  right.y = 0   
  forward = forward.normalized()
  right = right.normalized()
  var movement_dir = (forward * input_dir.y + right * input_dir.x).normalized()

  # Rotate player to face movement direction
  var target_rotation = atan2(movement_dir.x, movement_dir.z)
  rotation.y = lerp_angle(rotation.y, target_rotation, 0.1)

  # Apply movement
  if Input.is_action_pressed("ui_sprint"):
   velocity.x = movement_dir.x * sprint_speed
   velocity.z = movement_dir.z * sprint_speed
  else:
   velocity.x = movement_dir.x * run_speed
   velocity.z = movement_dir.z * run_speed
 else:
  velocity.x = move_toward(velocity.x, 0, run_speed)
  velocity.z = move_toward(velocity.z, 0, run_speed)

 # Handle jumping
 if Input.is_action_just_pressed("ui_jump") and is_on_floor():
  velocity.y = jump_speed
  is_jumping = true

 move_and_slide()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and control the character to observe the transitions and movement based on our state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F384%2F1%2AUVQ2U5vTar1d4d6NR9K-6Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F384%2F1%2AUVQ2U5vTar1d4d6NR9K-6Q.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  CollisionShape3D
&lt;/h1&gt;

&lt;p&gt;The CollisionShape3D node allows you to specify the boundaries of an object for collision detection, which is essential for handling interactions between objects in your game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU_iJ3Nc8inSCD6v2XhHACg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AU_iJ3Nc8inSCD6v2XhHACg.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Add a collision area to block the character from passing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a CollisionShape3D node as a child of a CharacterBody3D, RigidBody3D, orStaticBody3D. These nodes will block other collisions. To have a node pass through collisions, use an Area3D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F354%2F1%2AQRzgFlERgzzNuBC-AaBspQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F354%2F1%2AQRzgFlERgzzNuBC-AaBspQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Inspector, assign a Shape3D resource to the shape property of the CollisionShape3D. The shape you choose will depend on the shape of your entity. For example, a player might have a capsule shape, a pickup a sphere, an area a box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aea4R3lvyWD1AGIHfMnLxgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aea4R3lvyWD1AGIHfMnLxgQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let’s enable debugging to see our collisions in action. You can also change the color of your debug lines to make it more visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F419%2F1%2ANOSd3fnTzxguxb6hyRIROA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F419%2F1%2ANOSd3fnTzxguxb6hyRIROA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F870%2F1%2AcOxA2niIiepRMMMycaV9MA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F870%2F1%2AcOxA2niIiepRMMMycaV9MA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene to see how your player interacts with the collision shape. Since we used a StaticBody3D node, they should be blocked and unallowed to go through the collision.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F430%2F1%2AiemBd7zdmyhK9mUZmeQymg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F430%2F1%2AiemBd7zdmyhK9mUZmeQymg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  CharacterBody3D
&lt;/h1&gt;

&lt;p&gt;The CharacterBody3D node is a specialized class for physics bodies that are meant to be controlled or moved around by the user. Unlike other physics bodies such as the RigidBody3D or StaticBody3D node, CharacterBody3D is not affected by the engine’s physics properties like gravity or friction by default. Instead, you have to write code to control its behavior, giving you precise control over how it moves and reacts to collisions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Move a character with arrow keys, including handling gravity and jumping.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a CharacterBody3D node in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F376%2F1%2A-4hbxbUKbCUjDbzfqluSbA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F376%2F1%2A-4hbxbUKbCUjDbzfqluSbA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll see it has a warning icon next to it. This is because it needs a collision shape to be able to interact with the world. Add a CollisionShape3D as a child of the CharacterBody3D and set its shape to match your character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABYqu6oxrhOoqPZrxs0mIeg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABYqu6oxrhOoqPZrxs0mIeg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a MeshInstance3D node to this scene so that we can see our character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A64GjzYkilYz27m5V0eY0Eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A64GjzYkilYz27m5V0eY0Eg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll also need to attach a camera to your character so we can see them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmrrlF1W020oydhPZwtvu8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmrrlF1W020oydhPZwtvu8g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach a script to the CharacterBody3D to handle movement and jumping.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Character.gd

extends CharacterBody3D

# Variables
@export var speed = 5.0
@export var jump_force = 10.0
@export var gravity = 10.0

# Input for movement
func get_input():
 velocity.x = 0
 velocity.z = 0
 if Input.is_action_pressed("ui_up"):
  velocity.z -= speed
 if Input.is_action_pressed("ui_down"):
  velocity.z += speed
 if Input.is_action_pressed("ui_left"):
  velocity.x -= speed
 if Input.is_action_pressed("ui_right"):
  velocity.x += speed
 if is_on_floor() and Input.is_action_just_pressed("ui_accept"):
  velocity.y = jump_force

# Movement &amp;amp; Gravity
func _physics_process(delta):
 get_input()
 velocity.y -= gravity * delta
 move_and_slide()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and use the arrow keys to move the character and make it jump.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F402%2F1%2AtzE_tkvlCA4xcAyrceSuig.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F402%2F1%2AtzE_tkvlCA4xcAyrceSuig.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  StaticBody3D
&lt;/h3&gt;

&lt;p&gt;The StaticBody3D node is used to represent objects that do not move. This node is ideal for creating static elements in your game, such as walls, floors, and other immovable objects such as chests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create an obstacle.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a StaticBody3D node in your scene. Add a CollisionShape3Das a child of the StaticBody and set its shape to match the obstacle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADh5oa7jGmy8U7AaH9eK63g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADh5oa7jGmy8U7AaH9eK63g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a MeshInstance3Dof your choice so that we can see the item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUNehyPEx7RLAzKc0hKjxlA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUNehyPEx7RLAzKc0hKjxlA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene to see how your player interacts with the collision shape. They should be blocked and unallowed to go through the obstacle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F430%2F1%2AWBrXmZHytHjpj9FUZZvM9g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F430%2F1%2AWBrXmZHytHjpj9FUZZvM9g.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  RigidBody3D
&lt;/h1&gt;

&lt;p&gt;The RigidBody3D node is used for objects that are affected by the engine’s physics. These bodies can move, rotate, and respond to forces and collisions. They are ideal for creating dynamic objects that need realistic physics interactions, such as balls, bullets, moveable obstacles, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ai60wGCTzpVD5YDitEOvdmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a moveable obstacle.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a RigidBody3D node in your scene. Add a CollisionShape3Das a child of the RigidBody and set its shape to match the obstacle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AARFSR41Y6vjabgV4Lgs66A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AARFSR41Y6vjabgV4Lgs66A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a MeshInstance3Dof your choice so that we can see the item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AeqSwfBTNuuPnkgBn2F3f-A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AeqSwfBTNuuPnkgBn2F3f-A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since we don’t want the object to fly into space when we collide with it, we will need to increase its mass value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F431%2F1%2AnXNPYtYqp9OgqwNRMnVFdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F431%2F1%2AnXNPYtYqp9OgqwNRMnVFdw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use GDScript to apply forces or impulses to the rigid body if the player pushes it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody3D

# Vars
const run_speed = 3.0
const sprint_speed = 5.0
const jump_speed = 3.0
const gravity = 10

@export var push_force = 80.0

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var camera = $ThirdPersonCamera/Camera

var is_jumping = false

func _ready():
 Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _process(delta):
 handle_animation()

func _physics_process(delta):
 handle_movement(delta)
 handle_collisions()

func handle_animation():
 var input_dir = Input.get_vector("ui_right", "ui_left", "ui_down", "ui_up")
 if is_jumping:
  if animation_state.get_current_node() != "jump":
   animation_state.travel("jump")
 elif input_dir.length() &amp;gt; 0:
  if Input.is_action_pressed("ui_sprint"):
   if animation_state.get_current_node() != "sprint":
    animation_state.travel("sprint")
  else:
   if animation_state.get_current_node() != "walk":
    animation_state.travel("walk")
 else:
  if animation_state.get_current_node() != "idle":
   animation_state.travel("idle")

func handle_movement(delta):
 # Check if the player has landed
 if is_on_floor() and velocity.y == 0:
  is_jumping = false
 # Apply gravity
 velocity.y += -gravity * delta

 # Get input direction
 var input_dir = Input.get_vector("ui_left", "ui_right", "ui_down", "ui_up")
 if input_dir.length() &amp;gt; 0:
  # Calculate movement direction based on camera orientation
  var forward = -camera.global_transform.basis.z
  var right = camera.global_transform.basis.x
  forward.y = 0  
  right.y = 0   
  forward = forward.normalized()
  right = right.normalized()
  var movement_dir = (forward * input_dir.y + right * input_dir.x).normalized()

  # Rotate player to face movement direction
  var target_rotation = atan2(movement_dir.x, movement_dir.z)
  rotation.y = lerp_angle(rotation.y, target_rotation, 0.1)

  # Apply movement
  if Input.is_action_pressed("ui_sprint"):
   velocity.x = movement_dir.x * sprint_speed
   velocity.z = movement_dir.z * sprint_speed
  else:
   velocity.x = movement_dir.x * run_speed
   velocity.z = movement_dir.z * run_speed
 else:
  velocity.x = move_toward(velocity.x, 0, run_speed)
  velocity.z = move_toward(velocity.z, 0, run_speed)

 # Handle jumping
 if Input.is_action_just_pressed("ui_jump") and is_on_floor():
  velocity.y = jump_speed
  is_jumping = true

 move_and_slide()

# Handle Collisions
func handle_collisions():
 for i in range(get_slide_collision_count()):
  var collision = get_slide_collision(i)
  if collision.get_collider() is RigidBody3D:
   var collider = collision.get_collider() as RigidBody3D
   var impulse = -collision.get_normal() * push_force
   collider.apply_central_impulse(impulse)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and observe how the obstacle moves when the player pushes against it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F460%2F1%2AruaX3s_gYS69PL4TqksGvQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F460%2F1%2AruaX3s_gYS69PL4TqksGvQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  VehicleBody3D
&lt;/h1&gt;

&lt;p&gt;TheVehicleBody3D node is used to simulate a 3D vehicle with realistic physics. It requires VehicleWheel3D nodes for each wheel to function correctly.&lt;/p&gt;

&lt;p&gt;On our VehicleBody3D node, the most important properties are the engine_force, steer_angle, and brake_force properties. The engine_force allows our vehicle to move forward/backward. The steer_angle/steering properties allow our vehicle to move left/right. The brake_force property allows our car to stop.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a controllable vehicle with wheels.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;For this part, you will need to download a car and import it into your project. If you’re using my base template, I recommend downloading the &lt;a href="https://kenney.nl/assets/car-kit" rel="noopener noreferrer"&gt;Car Kit from Kenney&lt;/a&gt; and importing it into your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F390%2F1%2AzQQRI2dcix6JbUdzdNK7nA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F390%2F1%2AzQQRI2dcix6JbUdzdNK7nA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZbHNqylggFwhqDQKEuhtDg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZbHNqylggFwhqDQKEuhtDg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a VehicleBody3D node in your scene. You will need to give it a CollisionShape3D, and a mesh (use the one you imported).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4FnwpHVR2q1kNJ_wpj0L9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4FnwpHVR2q1kNJ_wpj0L9A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add VehicleWheel3D nodes as children of the VehicleBody3D node for each wheel. Name them FrontLWheel, BackLWheel, FrontRWheel, BackRWheel. Also move them into the positions of your wheels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AeCKaoQ1PRyjY2wuw4dM9NA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AeCKaoQ1PRyjY2wuw4dM9NA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll need to set your front wheels as the steering wheels, and your back wheels as your traction wheels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F436%2F1%2AOsxpv4DXk4W8bh0po6mLqA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F436%2F1%2AOsxpv4DXk4W8bh0po6mLqA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F453%2F1%2A1gYJnUU68gA8r2GvSOy5nA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F453%2F1%2A1gYJnUU68gA8r2GvSOy5nA.png" alt="Book of Nodes" width="453" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also attach a camera to your vehicle so you can follow it around.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFUMd5-vnZMKSPNfH6mlqeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFUMd5-vnZMKSPNfH6mlqeA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach a script to your vehicle to handle the vehicle’s movement and control. We’ll move our car with our arrow keys, and brake with our spacebar.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# VehicleBody.gd

extends VehicleBody3D

@onready var front_l_wheel = $FrontLWheel
@onready var front_r_wheel = $FrontRWheel
@onready var back_r_wheel = $BackRWheel
@onready var back_l_wheel = $BackLWheel

# Variables
@export var new_engine_force = 1000.0
@export var brake_force = 500.0
@export var steer_angle = 0.5

func _process(delta):
 handle_input()

func handle_input():
 var engine = 0.0
 var brake = 0.0
 var steer = 0.0

 if Input.is_action_pressed("ui_up"):
  engine = new_engine_force
 if Input.is_action_pressed("ui_down"):
  engine = -new_engine_force
 if Input.is_action_pressed("ui_left"):
  steer = steer_angle
 if Input.is_action_pressed("ui_right"):
  steer = -steer_angle
 if Input.is_action_pressed("ui_accept"):
  brake = brake_force

 front_l_wheel.engine_force = engine
 front_r_wheel.engine_force = engine
 front_l_wheel.brake = brake
 front_r_wheel.brake = brake
 front_l_wheel.steering = steer
 front_r_wheel.steering = steer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and try to control your vehicle. It should move around your map when controlled!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F650%2F1%2AahZBXzLYDisfAyUnNWVXxQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F650%2F1%2AahZBXzLYDisfAyUnNWVXxQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Area3D
&lt;/h1&gt;

&lt;p&gt;The Area3D node is used to detect when objects enter or exit a defined area. They do not represent physical bodies but are useful for triggering events such as cutscenes or map transitions, detecting overlaps, and creating zones for things such as enemy or loot spawning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A8LV6cwLaG3BA6bFWXZ11rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A8LV6cwLaG3BA6bFWXZ11rg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use the Area3D node’s on_body_entered() and on_body_exited() signals to determine whether or not a PhysicsBody has entered this zone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmBQh-XhpM3ACQKsKQ1d1uw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmBQh-XhpM3ACQKsKQ1d1uw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a trigger zone that detects when the player enters a specific area.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create an Area3D node in your scene. You also need to add a CollisionShape3D as a child of the Area and set its shape to define the trigger zone. Adjust the collision shape's properties to fit the dimensions of your trigger zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F374%2F1%2AqItKECN0JVVdgb8HrXugvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F374%2F1%2AqItKECN0JVVdgb8HrXugvw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACWzOEVXxYUpIRyUYrVRwEA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACWzOEVXxYUpIRyUYrVRwEA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach the Area3D node’s on_body_entered() and on_body_exited() signals to your script.&lt;/li&gt;
&lt;li&gt;Use GDScript to notify us when the Player enters or exits the area.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

func _on_area_3d_body_entered(body):
 if body.name == "Player":
  print("The player has entered the area!")

func _on_area_3d_body_exited(body):
 if body.name == "Player":
  print("The player has exited the area!")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable debugging so we can see when our Player enters/exits our area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F404%2F1%2A5tODHdR-eC7PlIYqPPQYTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F404%2F1%2A5tODHdR-eC7PlIYqPPQYTQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the scene and observe how the area detects when the Player enters or exits the defined zone. Each time the player enters/exits the zone, the game should be notified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F604%2F1%2ANDaXvAcYvK5iSZeBELHfTg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F604%2F1%2ANDaXvAcYvK5iSZeBELHfTg.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ar6IRvMokkRHUVSMr1gSmbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ar6IRvMokkRHUVSMr1gSmbw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  RayCast3D
&lt;/h1&gt;

&lt;p&gt;The RayCast3D node is used to cast a ray in a 3D space to detect objects along its path. This is useful for various purposes such as line-of-sight checks, shooting and attacking mechanics, and collision detection.&lt;/p&gt;

&lt;p&gt;It can collide with bodies such as StaticBody3D (useful for detecting loot and quest items), CharacterBody3D (useful for detecting interactions with enemies and NPCs), and RigidBody3D (useful for detecting interactions with moveable objects. It can also collide with areas, such as Area3D (useful for interactions with trigger zones).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANqUgtKtaqQAca45ezlkefw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANqUgtKtaqQAca45ezlkefw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Cast a ray from the player and detect what it hits.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a RayCast3D node to the Player in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F249%2F1%2AuxZNzTCA1GREQu0gRgs46A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F249%2F1%2AuxZNzTCA1GREQu0gRgs46A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the target_position property face the direction of your player (z: 1). You can also enable its collision with areas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F444%2F1%2ANw1PJz3scYymoT3o7G4QTw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F444%2F1%2ANw1PJz3scYymoT3o7G4QTw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFCMM6dS_aywIch58PNfDQw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFCMM6dS_aywIch58PNfDQw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can print what we are colliding with in our code.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody3D

# Vars
const run_speed = 3.0
const sprint_speed = 5.0
const jump_speed = 3.0
const gravity = 10

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var camera = $ThirdPersonCamera/Camera
@onready var ray_cast_3d = $RayCast3D

var is_jumping = false

func _ready():
 Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _process(delta):
 handle_animation()

    if ray_cast_3d.is_colliding():
        var collider = ray_cast_3d.get_collider()
        print("Raycast hit: ", collider.name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and interact with objects that have colliders. The raycast should detect the objects and notify the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AATbdQewjBZ1RiVK7tVd-Yw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AATbdQewjBZ1RiVK7tVd-Yw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AixMYQ9c73CsnJ9tJG7d0nQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AixMYQ9c73CsnJ9tJG7d0nQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Camera3D
&lt;/h1&gt;

&lt;p&gt;The Camera3D node is used to control the view of a 3D scene. It allows the screen to follow the player or other objects. Only one Camera can be active per viewport, and it registers itself in the nearest Viewport node.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;third-person games&lt;/strong&gt; , we usually attach the Camera3D node to a SpringArm3D node. The SpringArm node reacts to collisions in the environment. It ensures that the camera moves closer to the player when there are obstacles, preventing the camera from clipping through objects.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;first-person games&lt;/strong&gt; , we usually attach the Camera3D directly to our Pivot — such as our Player head. This way we “see” from the player’s perspective.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;“God-Mode”&lt;/strong&gt; , we attach the Camera to our World scene so that we can get a birds-eye view of the environment. This usually requires a bit more configuration and coding, as you have to make the camera able to move, rotate, and zoom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aq-NnVoRSAujwqSkA8qxiSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aq-NnVoRSAujwqSkA8qxiSA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a “God Mode” 3D camera that can move, zoom, and rotate based on user input.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Camera3D node to your Main (World) scene. Make sure this camera is set to ‘current’, and all other cameras are disabled.&lt;/li&gt;
&lt;li&gt;Also move the camera up on the y-axis (10), and rotate it slightly on the x-axis (-45) to point down at your world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APZTyIX41RrsYxhbTdrsqUQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APZTyIX41RrsYxhbTdrsqUQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the inputs to zoom, move, and rotate your camera.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKNsnPDRESTjzHjGNSEfg0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKNsnPDRESTjzHjGNSEfg0g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZLjsA4EUjyXRT12kfv3MgA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZLjsA4EUjyXRT12kfv3MgA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use GDScript to handle the camera’s zoom, movement, and rotation. You can do this in a custom Camera.gd script (preferred), or directly in your root script.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

@onready var camera_3d = $Camera3D

@export var zoom_speed = 50.0
@export var move_speed = 5.0 # Adjusted to a more reasonable value
@export var rotate_speed = 0.5 # Adjusted to a more reasonable value
@export var min_zoom = 10.0
@export var max_zoom = 100.0

var target_fov = 70.0
var camera_drag = Vector2.ZERO
var camera_movement = Vector3.ZERO
var sensibility = 0.001

func _process(delta):
 handle_zoom(delta)
 handle_movement(delta)
 handle_rotation(delta)

func handle_zoom(delta):
 if Input.is_action_pressed("zoom_in"):
  camera_3d.fov -= zoom_speed * delta
 if Input.is_action_pressed("zoom_out"):
  camera_3d.fov += zoom_speed * delta
 camera_3d.fov = clamp(camera_3d.fov, min_zoom, max_zoom)

func handle_movement(delta):
 if Input.is_action_just_pressed("camera_drag"):
  camera_drag = get_viewport().get_mouse_position()
 if Input.is_action_pressed("camera_drag"):
  camera_movement.x += (get_viewport().get_mouse_position().x - camera_drag.x) * sensibility
  camera_movement.z += (get_viewport().get_mouse_position().y - camera_drag.y) * sensibility
 camera_3d.position += camera_movement * move_speed * delta
 camera_movement = lerp(camera_movement, Vector3.ZERO, 0.2)

func handle_rotation(delta):
 if Input.is_action_pressed("rotate_left"):
  camera_3d.rotate_y(rotate_speed * delta)
 if Input.is_action_pressed("rotate_right"):
  camera_3d.rotate_y(-rotate_speed * delta)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and use the defined input actions to move, zoom, and rotate the camera.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F520%2F1%2AohXYksHkIh-rUMQewp6pOg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F520%2F1%2AohXYksHkIh-rUMQewp6pOg.gif" alt="Book of Nodes" width="200" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  DirectionalLight3D
&lt;/h1&gt;

&lt;p&gt;The DirectionalLight3D node is used to simulate sunlight or moonlight in our 3D environment. It emits light in a specific direction, affecting all objects in the scene equally, regardless of their distance from the light source. This type of light is useful for outdoor scenes where you need consistent lighting across the entire scene.&lt;/p&gt;

&lt;p&gt;This node’s two main properties are the energy and color properties. The energy property determines how bright/dim the light is, and the color is the shading of the light. You can also change the Mode of the shadows, which will change the way your shadows are rendered. By default, PSSM 2 is a good option to choose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvikN4u-Biq7ucKvzIywHVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvikN4u-Biq7ucKvzIywHVQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 3D environments, your light will also be influenced by your WorldEnvironment node, which contains the sky of your world.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Illuminate a scene with sunlight.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Create a DirectionalLight3D node in your scene.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F353%2F1%2ASnf8JESiWkvaXfFlNj7eaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F353%2F1%2ASnf8JESiWkvaXfFlNj7eaw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANU09iI1eCJiBVNluerw9Mg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANU09iI1eCJiBVNluerw9Mg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default, the light and energy looks pretty good. We can change these values if you want. For instance, we can make the energy brighter and the color darker to simulate night time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqxjXwIbpF_Ae_QkShNwICQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqxjXwIbpF_Ae_QkShNwICQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now let’s do something fun. I recommend using shaders with this node, but just for testing sake, let’s have it randomize its color each second.&lt;/li&gt;
&lt;li&gt;Add a Timer node to your scene. In the Inspector Panel, enable autostart, and connect its timeout signal to your script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F380%2F1%2AvSao5ewcioim5pIhS9NB2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F380%2F1%2AvSao5ewcioim5pIhS9NB2w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F576%2F1%2ATeUoA8w2u5Avz4nCLpq8aQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F576%2F1%2ATeUoA8w2u5Avz4nCLpq8aQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F897%2F1%2A-Pp33-7X6r0KNciNEZ8kYQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F897%2F1%2A-Pp33-7X6r0KNciNEZ8kYQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your code, let’s randomize our light’s color every time the timer times out (every second).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

@onready var directional_light_3d = $World/DirectionalLight3D

func _on_timer_timeout():
 directional_light_3d.color = Color(randf(), randf(), randf()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and enjoy the overstimulation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F632%2F1%2AmebhHIwL1dPbkuwlxVo-EQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F632%2F1%2AmebhHIwL1dPbkuwlxVo-EQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  SpotLight3D
&lt;/h1&gt;

&lt;p&gt;The SpotLight3D node emits light in a cone shape, illuminating objects within the cone’s range. This type of light is useful for creating focused lighting effects, such as flashlights or stage lights.&lt;/p&gt;

&lt;p&gt;This node’s two main properties are the energy , color, specular, and range, and projectorproperties. The energy property determines how bright/dim the light is. The color is the shading of the light. The specular property affects how reflective surfaces appear under the spotlight. The range property defines the maximum distance the light can reach. The projector property allows us to give our light a texture, such as stained glass or a vignette effect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvikN4u-Biq7ucKvzIywHVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvikN4u-Biq7ucKvzIywHVQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a flashlight attached to your player.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;To your player, attach a Spotlight3D node. Move this node into one of their hands, and rotate it on the y-axis (180) so that it faces the direction that the player is facing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcHORCNybRYJg5wrzYKvS5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcHORCNybRYJg5wrzYKvS5w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play around with the energy, range, angle, color, and specular values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F451%2F1%2Ap9SwRzBdYcocoaa7ARHMrQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F451%2F1%2Ap9SwRzBdYcocoaa7ARHMrQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5Ffv7jS4YIxk9WW7D8xf3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5Ffv7jS4YIxk9WW7D8xf3g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This light looks too bright. It needs to look more like a flashlight. Download &lt;a href="https://opengameart.org/content/flashlight-pattern-incandescent" rel="noopener noreferrer"&gt;this&lt;/a&gt; texture, and drag it into your projector property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F414%2F1%2Ak7atlqJXZCui-_F7YWtqhQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F414%2F1%2Ak7atlqJXZCui-_F7YWtqhQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATgno1hg1l9c8bZlaNnJkvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATgno1hg1l9c8bZlaNnJkvg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, let’s move this flashlight when we move our camera.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody3D

# Vars
const run_speed = 3.0
const sprint_speed = 5.0
const jump_speed = 3.0
const gravity = 10

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var camera = $ThirdPersonCamera/Camera
@onready var flashlight = $SpotLight3D

var is_jumping = false

func _ready():
 Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _process(delta):
 handle_animation()

func _physics_process(delta):
 handle_movement(delta)

func handle_animation():
 var input_dir = Input.get_vector("ui_right", "ui_left", "ui_down", "ui_up")
 if is_jumping:
  if animation_state.get_current_node() != "jump":
   animation_state.travel("jump")
 elif input_dir.length() &amp;gt; 0:
  if Input.is_action_pressed("ui_sprint"):
   if animation_state.get_current_node() != "sprint":
    animation_state.travel("sprint")
  else:
   if animation_state.get_current_node() != "walk":
    animation_state.travel("walk")
 else:
  if animation_state.get_current_node() != "idle":
   animation_state.travel("idle")

func handle_movement(delta):
 # Check if the player has landed
 if is_on_floor() and velocity.y == 0:
  is_jumping = false
 # Apply gravity
 velocity.y += -gravity * delta

 # Get input direction
 var input_dir = Input.get_vector("ui_left", "ui_right", "ui_down", "ui_up")
 if input_dir.length() &amp;gt; 0:
  # Calculate movement direction based on camera orientation
  var forward = -camera.global_transform.basis.z
  var right = camera.global_transform.basis.x
  forward.y = 0  
  right.y = 0   
  forward = forward.normalized()
  right = right.normalized()
  var movement_dir = (forward * input_dir.y + right * input_dir.x).normalized()

  # Rotate player to face movement direction
  var target_rotation = atan2(movement_dir.x, movement_dir.z)
  rotation.y = lerp_angle(rotation.y, target_rotation, 0.1)

  # Apply movement
  if Input.is_action_pressed("ui_sprint"):
   velocity.x = movement_dir.x * sprint_speed
   velocity.z = movement_dir.z * sprint_speed
  else:
   velocity.x = movement_dir.x * run_speed
   velocity.z = movement_dir.z * run_speed
 else:
  velocity.x = move_toward(velocity.x, 0, run_speed)
  velocity.z = move_toward(velocity.z, 0, run_speed)

 # Handle jumping
 if Input.is_action_just_pressed("ui_jump") and is_on_floor():
  velocity.y = jump_speed
  is_jumping = true

 move_and_slide()

 # Rotate flashlight to match camera orientation
 flashlight.global_rotation = camera.global_rotation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and move your camera. Your flashlight should shine in that direction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F528%2F1%2AoctdVXI8aaLbvAEgxheIbQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F528%2F1%2AoctdVXI8aaLbvAEgxheIbQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  OmniLight3D
&lt;/h1&gt;

&lt;p&gt;The OmniLight3D node emits light in all directions from a single point, similar to a light bulb. This type of light is useful for creating ambient lighting or point light sources.&lt;/p&gt;

&lt;p&gt;This node’s two main properties are the energy , color, specular, and range, and projectorproperties. The energy property determines how bright/dim the light is. The color is the shading of the light. The specular property affects how reflective surfaces appear under the spotlight. The range property defines the maximum distance the light can reach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvikN4u-Biq7ucKvzIywHVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvikN4u-Biq7ucKvzIywHVQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a flickering torch.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In your scene, add a OmniLight3D node. Move it to where you want your light to shine from.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AjA0xOviX3C5nOu_-c_qPdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AjA0xOviX3C5nOu_-c_qPdg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play around with the energy, range,color, and specular values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuaGlXROJbETPztWLIclpAw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuaGlXROJbETPztWLIclpAw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just for fun, let’s give it a flicker effect. We’ll do this via an AnimationPlayer node.&lt;/li&gt;
&lt;li&gt;Create a new animation in the AnimationPlayer.&lt;/li&gt;
&lt;li&gt;Add a track for the energy property of the OmniLight3D.&lt;/li&gt;
&lt;li&gt;Add keyframes to the energy track to simulate flickering.&lt;/li&gt;
&lt;li&gt;Enable looping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F357%2F1%2AE4bnU5Gj9qqMsfREKgrinQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F357%2F1%2AE4bnU5Gj9qqMsfREKgrinQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZn948Qe1mQAWCWQ1iWvleA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZn948Qe1mQAWCWQ1iWvleA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_TApuJaOSYE8NvyyDA0txw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A_TApuJaOSYE8NvyyDA0txw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A46DsB-vc0ogQP8yhgDEAdQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A46DsB-vc0ogQP8yhgDEAdQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then play this animation via the code when the game loads.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

@onready var animation_player = $AnimationPlayer

func _ready():
 animation_player.play("flicker")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the scene and observe the player’s color changes when they go into the flickering lights.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F754%2F1%2AggDu9XQlpdYk_zcRy-iepQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F754%2F1%2AggDu9XQlpdYk_zcRy-iepQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  BoneAttachment3D
&lt;/h1&gt;

&lt;p&gt;When importing a 3D model with a skeleton from 3D software such as Blender, the Skeleton3Dnode should automatically be populated with bones if the model is correctly rigged, exported, and imported. Bone3Dare the parts of the body — such as the hands, arms, legs, etc.&lt;/p&gt;

&lt;p&gt;The BoneAttachment3Dnode is used to attach nodes to specific bones in a Skeleton3D. This allows you to dynamically attach objects to bones, which will follow the bone’s transformations. For example, we can attach a flashlight to our player’s hand, or a bow on our player’s back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Am_ZJa0e51qfzLZfAVnE_og.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Am_ZJa0e51qfzLZfAVnE_og.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we look at the Player character in the base template, we can see that their Skeleton3D node from is already populated with bones. This came from the model (.glb) itself — we didn’t have to manually create this in Godot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F449%2F1%2Am9fcMIayaX8sXbdz2jREiA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F449%2F1%2Am9fcMIayaX8sXbdz2jREiA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Attach a weapon to the right hand of our player.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation Steps
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In your Player scene, add aBoneAttachment3D node as a child of the Skeleton3D node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F407%2F1%2AVQps0EG54te6g8k676F8NQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F407%2F1%2AVQps0EG54te6g8k676F8NQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the bone_name property of theBoneAttachment3D to the name of the bone you want to attach to. In our case, it should be the arm-right.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F442%2F1%2AAEKBgwex_BdmkYljwWFj0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F442%2F1%2AAEKBgwex_BdmkYljwWFj0g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F439%2F1%2AOFzteyHQFX8S9T823JUs-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F439%2F1%2AOFzteyHQFX8S9T823JUs-Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the objects you want to attach as children of the BoneAttachment3D nodes. In our case, we want to add a weapon. Since we don’t have weapons in the base template, we will use the cane instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F413%2F1%2A5F9Pb40leECmNC1tku_hcQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F413%2F1%2A5F9Pb40leECmNC1tku_hcQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move the cane into the players hand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F915%2F1%2A9HZFNEIgb9bXUM0nd76IaA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F915%2F1%2A9HZFNEIgb9bXUM0nd76IaA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In our script, let’s handle the attachment and detachment of this “weapon”. We also need to add an input to handle this action.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AjwIz0b5T20z830IjxpRgXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AjwIz0b5T20z830IjxpRgXQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Player.gd

extends CharacterBody3D

# Vars
const run_speed = 3.0
const sprint_speed = 5.0
const jump_speed = 3.0
const gravity = 10

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var camera = $ThirdPersonCamera/Camera

@onready var bone_attachment_3d = $"character-female-b2/character-female-b/Skeleton3D/BoneAttachment3D"

## Older code

func _input(event):
 if event.is_action_pressed("ui_equip"):
  equip_object()

func equip_object():
 bone_attachment_3d.visible = !bone_attachment_3d.visible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene. Your weapon should equip/unequip if you press TAB. When you move, the weapon should also move naturally with your bone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F578%2F1%2AQZOPKFG810ajF-n_YUqZkQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F578%2F1%2AQZOPKFG810ajF-n_YUqZkQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AudioStreamPlayer3D and AudioStreamPlayer
&lt;/h1&gt;

&lt;p&gt;These nodes are used to play audio in our games. We use the AudioStreamPlayer to play audio equally across our scene (such as background music or ambient sounds), and the AudioStreamPlayer3D to play audio positionally (such as from our players or NPCs).&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Play ambient music in the background, and sounds from the player when they move.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Download your sound effects. You can find free ones on &lt;a href="https://pixabay.com/sound-effects/search/game/" rel="noopener noreferrer"&gt;Pixabay&lt;/a&gt;. Look for ones that work well in the background (they loop), and ones that are short effects, such as jumping sounds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aow1d7YpvsSWPYqah-Stg5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aow1d7YpvsSWPYqah-Stg5w.png" alt="Book of Nodes" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AiCzB9Df3lRp71foRVuc8Ww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AiCzB9Df3lRp71foRVuc8Ww.png" alt="Book of Nodes" width="800" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an AudioStreamPlayer node to play background audio. Add an AudioStreamPlayer3D node to play positional audio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F411%2F1%2ANFqsWrJkq0jtlctOkdpzIw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F411%2F1%2ANFqsWrJkq0jtlctOkdpzIw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will need to reimport your audio that is supposed to loop. Double click it, and enable looping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F732%2F1%2AfznPUW2tCpy9aqxI9XeGsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F732%2F1%2AfznPUW2tCpy9aqxI9XeGsg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the stream property to the desired audio file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F573%2F1%2AlF6ZSKfDoI6NezPU-FjnlQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F573%2F1%2AlF6ZSKfDoI6NezPU-FjnlQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F562%2F1%2AH1Rs8wlKuub_9WnrMV3GrA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F562%2F1%2AH1Rs8wlKuub_9WnrMV3GrA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust properties like volume_db, and pitch_scale if needed. We’ll enable autoplay on our AudioStreamPlayer node since that is our background music.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F575%2F1%2Ayxwvs01ZT6APelQ1_7KyTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F575%2F1%2Ayxwvs01ZT6APelQ1_7KyTg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We also want to enable the emission property on our AudiostreamPlayer3D so that the audio can sound more distanced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F564%2F1%2AvypWmWaanRtCUTrfRXdVAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F564%2F1%2AvypWmWaanRtCUTrfRXdVAQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will play our sound effect audio (AudioStreamPlayer3D) when our player enters a certain area. To do this, add an Area3D node to your scene with a collision body, and attach its on_body_entered() signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A-7PIdscnhjtVmN2WJK6Epw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A-7PIdscnhjtVmN2WJK6Epw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F999%2F1%2AmQXuMFMlidt2tDPuHG4s3A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F999%2F1%2AmQXuMFMlidt2tDPuHG4s3A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now play the audio when the player enters the area.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

@onready var audio_stream_player_3d = $AudioStreamPlayer3D

func _on_area_3d_body_entered(body):
 if body.name == "Player":
  audio_stream_player_3d.play()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene. The background music should play, and the sound effect should play when your player enters the area.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  WorldEnvironment
&lt;/h1&gt;

&lt;p&gt;The WorldEnvironment node configures the default environment settings for a scene, including lighting, post-processing effects, and background settings. This node allows you to add a bunch of environmental effects, such as a skybox, fog, shadows, etc.&lt;/p&gt;

&lt;p&gt;Everything you see in the screenshot below (the sky, light, fog) was done with the help of the WorldEnvironment node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYeBGXP2rpQOfi4NZGCF6iQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYeBGXP2rpQOfi4NZGCF6iQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The most common properties you will change on this node will be:&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Fog
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Fog makes distant objects fade into a uniform color, simulating atmospheric effects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Light Color: The color of the fog.&lt;/li&gt;
&lt;li&gt;Density: The ‘thickness’ of the fog until it is fully opaque.&lt;/li&gt;
&lt;li&gt;Sky Affect: Adjusts the fog color based on the sun’s energy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Volumetric Fog
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Volumetric fog provides a more realistic fog effect by interacting with the lights in the scene.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Density: The base exponential density of the volumetric fog.&lt;/li&gt;
&lt;li&gt;Albedo: The color of the fog when interacting with lights.&lt;/li&gt;
&lt;li&gt;Emission: The emitted light from the fog, useful for establishing ambient color.&lt;/li&gt;
&lt;li&gt;Emission Energy: The brightness of the emitted light.&lt;/li&gt;
&lt;li&gt;Anisotropy: The direction of scattered light through the fog.&lt;/li&gt;
&lt;li&gt;Length: The distance over which the fog is computed.&lt;/li&gt;
&lt;li&gt;Detail Spread: The distribution of detail in the fog.&lt;/li&gt;
&lt;li&gt;Ambient Inject: Scales the strength of ambient light used in the fog.&lt;/li&gt;
&lt;li&gt;Sky Affect: Controls how much the fog affects the background sky.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Glow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Glow adds bloom effects to bright areas, enhancing the visual appeal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Intensity: The strength of the glow effect.&lt;/li&gt;
&lt;li&gt;Strength: The brightness for the glow effect.&lt;/li&gt;
&lt;li&gt;Blend Mode: The blending mode for the glow effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Tonemapping
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Tonemapping adjusts the color balance and contrast of the scene.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Mode: The tone-mapping algorithm (e.g., Linear, Reinhard, Filmic).&lt;/li&gt;
&lt;li&gt;Exposure: Adjusts the overall exposure of the scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ambient Light
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Ambient light provides a base level of illumination for the scene, ensuring that no part of the scene is completely dark.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Color: The color of the ambient light.&lt;/li&gt;
&lt;li&gt;Energy: The intensity of the ambient light.&lt;/li&gt;
&lt;li&gt;Sky Contribution: The amount of light contributed by the sky.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Sky
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; The sky provides the background for the scene, which can be a solid color, a skybox, or a custom shader.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Sky: The type of sky (e.g., PanoramaSky, ProceduralSky).&lt;/li&gt;
&lt;li&gt;Custom FOV: The intensity of the sky’s contribution to the scene lighting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Background
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; The background sets the visual backdrop for the scene, which can be a solid color, a sky, or a custom shader.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Mode: The background mode (e.g., Clear Color, Sky, Custom Color).&lt;/li&gt;
&lt;li&gt;Energy Multiplier: The intensity of the background’s contribution to the scene lighting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a spooky atmosphere.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a WorldEnvironment node to your scene. To this node, add an Environment resource and configure it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F415%2F1%2A_e9RG2fh4sdU3r6A_yOO1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F415%2F1%2A_e9RG2fh4sdU3r6A_yOO1g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F574%2F1%2A1hYVjXdhjSg85mAi9ptI0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F574%2F1%2A1hYVjXdhjSg85mAi9ptI0g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the background to be a color. Set the color to be black.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F533%2F1%2Ar5liIVvZwv76KozP_h6XyQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F533%2F1%2Ar5liIVvZwv76KozP_h6XyQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the ambient light color and energy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F551%2F1%2AsZla7Kbv3o5McrDWmkv5Yw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F551%2F1%2AsZla7Kbv3o5McrDWmkv5Yw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F897%2F1%2A6K5n6GrJfRdwH4_i9u0p9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F897%2F1%2A6K5n6GrJfRdwH4_i9u0p9g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everything is too dark. Let’s enable our fog and change our properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F537%2F1%2AO6dfjIaTzYnM4gsFyn_mhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F537%2F1%2AO6dfjIaTzYnM4gsFyn_mhw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F911%2F1%2AktEycOOEzVtXoRB5IMPmFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F911%2F1%2AktEycOOEzVtXoRB5IMPmFw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let’s lighten the mood. Enable the glow property, and change its properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F524%2F1%2AQfFLHIPuhAAejerTOMLfnQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F524%2F1%2AQfFLHIPuhAAejerTOMLfnQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F893%2F1%2A83raXR6m_iMKax7E9Givow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F893%2F1%2A83raXR6m_iMKax7E9Givow.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene. Your game should look a little bit more spooky now!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AK31sCUvbzp6-oZSZPCQ8vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AK31sCUvbzp6-oZSZPCQ8vg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  NavigationAgent3D, NavigationObstacle3D, NavigationRegion3D
&lt;/h1&gt;

&lt;p&gt;The NavigationAgent, NavigationObstacle, and NavigationRegion nodes are used to manage navigation and pathfinding in both 2D and 3D environments. These nodes help create dynamic and realistic movement for characters and objects, allowing them to navigate around obstacles and follow paths.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The NavigationAgent3Dnode is used to move characters along a path while avoiding obstacles.&lt;/li&gt;
&lt;li&gt;The NavigationObstacle3D node is used to create obstacles that navigation agents will avoid.&lt;/li&gt;
&lt;li&gt;The NavigationRegion3D node defines areas where navigation is allowed or restricted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0iZy9Ub05IbpDC6JYms-nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0iZy9Ub05IbpDC6JYms-nw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These three nodes combined allow us to create a more immersive world through mechanics such as NPC and Enemy roaming, particle movements, and controlled entity spawning.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create an NPC that roams around a certain area on the map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In your Main scene, add a NavigationRegion3D to your scene to define the roaming area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F406%2F1%2Ao076ltZ665uWsIr4Q_VtDQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F406%2F1%2Ao076ltZ665uWsIr4Q_VtDQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new NavigationMesh resource for this node so that we can define our region. Also move it to where you want your region to be.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F575%2F1%2AtLezqqJCU7PjaY7eJvUpcA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F575%2F1%2AtLezqqJCU7PjaY7eJvUpcA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F422%2F1%2Amds9jjd0Vv8Iq541Qylf0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F422%2F1%2Amds9jjd0Vv8Iq541Qylf0g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now to actually add our region, we’ll need to add our “floor” as a child of this NavigationRegion node. Since I’m not sure if you are using Terrains or GridMaps, we’ll use a MeshInstance3D for this.&lt;/li&gt;
&lt;li&gt;Add a MeshInstance3D node as a child to this node. Change its size to something like 10 x 10 m.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADr4q2M3FSewnnZByqXCGZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADr4q2M3FSewnnZByqXCGZA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move your region so the floor is below the grass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F427%2F1%2Atzc6ea3HXfbq0tEJWscVCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F427%2F1%2Atzc6ea3HXfbq0tEJWscVCg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now all we need to do is select our NavigationRegion node and select &lt;strong&gt;“Bake Navigation”&lt;/strong&gt;. You’ll see a blue-colored polygon get drawn over our floor, that is our navigation region!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1013%2F1%2A5wgxfKs6sY8U41t33RzSbA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1013%2F1%2A5wgxfKs6sY8U41t33RzSbA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a new scene, create your NPC using a CharacterBody3Dnode as the root node. Add the collisions and animations for this entity just as you did for your player.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGcJMy-6MunMbE5xS_y8FlA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGcJMy-6MunMbE5xS_y8FlA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To your NPC scene, add a NavigationAgent3D node. The NPC will be assigned to this agent so that they can roam in the region. Enable avoidance for this NPC so that they can avoid obstacles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F415%2F1%2AX4ZucJi_IehUZF3Tpd414A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F415%2F1%2AX4ZucJi_IehUZF3Tpd414A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F593%2F1%2AW9KnazMVlRUqCcpNhOghAg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F593%2F1%2AW9KnazMVlRUqCcpNhOghAg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach a script to your NPC. We will then need to connect our signals from our NavigationAgent3D node to &lt;strong&gt;1)&lt;/strong&gt; compute the avoidance velocity of our NPC, and &lt;strong&gt;2)&lt;/strong&gt; redirect our NPC when that target is reached. For moving the NPC whilst avoiding obstacles, attach the velocity_computed signal to your script. For redirecting the NPC, attach the navigation_finished signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F773%2F1%2Amn5ZgB0cHuS7ngOUNrRLXg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F773%2F1%2Amn5ZgB0cHuS7ngOUNrRLXg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F868%2F1%2A4405zy_NQl9ExvNOL62rRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F868%2F1%2A4405zy_NQl9ExvNOL62rRw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We also want our NPC to pause before redirecting. To do this, we will add a Timer node to our scene. Enable its one_shot property, and change its wait_time to however long you want the NPC to wait before roaming again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A19tBkMQz_Az55jOczidhmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A19tBkMQz_Az55jOczidhmg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also attach its timeout() signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F689%2F1%2AYodNFScnE7kGEF8w0gwWjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F689%2F1%2AYodNFScnE7kGEF8w0gwWjg.png" alt="Book of Nodes" width="689" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now add your roaming functionality.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### NPC.gd

extends CharacterBody3D

@onready var navigation_agent_3d = $NavigationAgent3D
@onready var navigation_region = $"../NavigationRegion3D/MeshInstance3D"
@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var timer = $Timer

# Variables
@export var movement_speed: float = 1.0
var roaming_area: AABB
var target_position: Vector3

func _ready():
 # Add a delay to ensure the navigation map is loaded
 await get_tree().create_timer(1).timeout
 set_roaming_area()
 set_random_target()

func _physics_process(delta):
 # Move NPC towards the target
 var next_path_position: Vector3 = navigation_agent_3d.get_next_path_position()
 var new_velocity: Vector3 = global_position.direction_to(next_path_position) * movement_speed
 if navigation_agent_3d.avoidance_enabled:
  navigation_agent_3d.velocity = new_velocity
 else:
  _on_navigation_agent_3d_velocity_computed(new_velocity)

 # Rotate NPC to face the direction of movement
 if velocity.length() &amp;gt; 0:
  var target_rotation = atan2(velocity.x, velocity.z)
  rotation.y = lerp_angle(rotation.y, target_rotation, 0.1)

 # Play walking animation
 if velocity != Vector3.ZERO:
  animation_state.travel("walk")
 else:
  animation_state.travel("idle")

 move_and_slide()

func set_roaming_area():
 # Set the roaming area based on the MeshInstance3D's bounding box
 roaming_area = navigation_region.get_aabb()
 print("Roaming area: ", roaming_area)

func set_random_target():
 # Set next roaming position
 target_position = Vector3(
  randf_range(-roaming_area.position.x, roaming_area.position.x),
  randf_range(-roaming_area.position.y, roaming_area.position.y),
  randf_range(-roaming_area.position.z, roaming_area.position.z)
 )
 navigation_agent_3d.set_target_position(target_position)

func _on_navigation_agent_3d_velocity_computed(safe_velocity):
 # Move NPC
 velocity = safe_velocity

func _on_timer_timeout():
 # Move NPC again
 set_random_target()

func _on_navigation_agent_3d_navigation_finished():
 # When path reached, redirect NPC
 velocity = Vector3.ZERO
 animation_state.travel("idle")
 timer.start()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Instance your NPC in your Main scene. Move them into your region.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AwJ5FfKNxc0CawL3CpmoxAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F1%2AwJ5FfKNxc0CawL3CpmoxAA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optionally, add NavigationObstacle3D nodes to create obstacles. Add this node to a mesh with a collision shape.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F423%2F1%2Ad2whKSflYy1IAxwKMQJrYA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F423%2F1%2Ad2whKSflYy1IAxwKMQJrYA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ap7hCXUGAAW9Vz1MaBbAfrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ap7hCXUGAAW9Vz1MaBbAfrg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene and see your NPC randomly roam. They should avoid your obstacles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F584%2F1%2AACaqos7LQL0DwTR99dsPRA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F584%2F1%2AACaqos7LQL0DwTR99dsPRA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Path3D and PathFollow3D
&lt;/h1&gt;

&lt;p&gt;The Path3D and PathFollow3D nodes work together to create and follow paths in a 3D space. The Path3D node is used to define a path using a sequence of points. I like this more than using a NavMesh because it allows you to create and visualize a path in the Godot editor, instead of randomizing it. The PathFollow3D node is used to make an object follow a path defined by a Path3D node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARCM31wIPKpff6QlV5OIs8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARCM31wIPKpff6QlV5OIs8g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create an NPC that roams on a defined path on the map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Path3D node in your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F435%2F1%2AfuWjdCSIS7pb1pehmrYK4Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F435%2F1%2AfuWjdCSIS7pb1pehmrYK4Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a PathFollow3D node as a child of the Path3D.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F431%2F1%2AXNWvOcAIn5lrWLbFuQ0TFg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F431%2F1%2AXNWvOcAIn5lrWLbFuQ0TFg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable its use_model_front property so that our NPC will always move whilst facing the front.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F477%2F1%2AwQRl-8I7Amkdv-YX_Pm_yQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F477%2F1%2AwQRl-8I7Amkdv-YX_Pm_yQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a new scene, create your NPC using a CharacterBody3Dnode as the root node. Add the collisions and animations for this entity just as you did for your player.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGcJMy-6MunMbE5xS_y8FlA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGcJMy-6MunMbE5xS_y8FlA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach your NPC to your PathFollow3D node. This will tell the game that this is the object that should follow this Path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F439%2F1%2AzqCJkKK-48qxMWilSVVn7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F439%2F1%2AzqCJkKK-48qxMWilSVVn7w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Awt57KntwjYf4Ckzj4qEEuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Awt57KntwjYf4Ckzj4qEEuw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can draw our path. In the Godot editor, select the Path3D node. Use the “Add Point” button in the toolbar to add points to draw the path shape that your NPC has to follow. Select the point to move it on your map.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2AyWwcqCO3dyx9BNSD5t3S5A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F369%2F1%2AyWwcqCO3dyx9BNSD5t3S5A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYoNVcQdhM8b4YUQW3cUQvQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYoNVcQdhM8b4YUQW3cUQvQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F467%2F1%2AMXSX4QLrQYPhCacgVgS6dA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F467%2F1%2AMXSX4QLrQYPhCacgVgS6dA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add more points to complete your path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F891%2F1%2A8yDlGp-HKstaNV1bMadMTw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F891%2F1%2A8yDlGp-HKstaNV1bMadMTw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F450%2F1%2A9S8sowQHFYRnx0OtIE34oA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F450%2F1%2A9S8sowQHFYRnx0OtIE34oA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure your path is on the ground, otherwise your NPC will fly!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F962%2F1%2AGmwGGYXRfq7WoKWrLg7nsA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F962%2F1%2AGmwGGYXRfq7WoKWrLg7nsA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F489%2F1%2AqT7AldbF2SWpubxevieWrQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F489%2F1%2AqT7AldbF2SWpubxevieWrQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With your path created, attach a script to your NPC. Then, add the logic for them to move along the path.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### NPC.gd

extends CharacterBody3D

@onready var animation_tree = $AnimationTree
@onready var animation_state = animation_tree.get("parameters/playback")
@onready var path_follow = get_parent()

# Vars
@export var movement_speed: float = 2.0
var current_offset: float = 0.0
var path_length: float = 0.0
var direction: int = 1
var previous_position: Vector3 = Vector3.ZERO

func _ready():
 # Get the total length of the path
 path_length = path_follow.get_parent().curve.get_baked_length()

func _physics_process(delta):
 # Update the progress along the path
 update_path_progress(delta)

 # Calculate the velocity based on the change in position
 var current_position = path_follow.global_transform.origin
 var velocity = (current_position - previous_position) / delta
 previous_position = current_position

 # Update the animation based on the velocity
 update_animation(velocity)

 # Update the NPC's position to follow the PathFollow3D node
 global_transform.origin = current_position

 # Rotate NPC to face the direction of movement
 if velocity.length() &amp;gt; 0:
  var target_rotation = atan2(velocity.x, velocity.z)
  rotation.y = lerp_angle(rotation.y, target_rotation, 0.1)

 move_and_slide()

func update_path_progress(delta):
 current_offset += movement_speed * delta * direction

 # Reverse direction if the end or start of the path is reached
 if current_offset &amp;gt;= path_length or current_offset &amp;lt;= 0:
  direction *= -1 # Reverse the direction
 current_offset = clamp(current_offset, 0, path_length)

 # Update the progress of the PathFollow3D node
 path_follow.progress = current_offset

func update_animation(velocity: Vector3):
 if velocity.length() == 0:
  animation_state.travel("idle")
 else:
  animation_state.travel("walk")
  animation_tree.set("parameters/walk/blend_position", velocity.normalized())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your scene and see your NPC roam. They should follow your path in a zig-zag (back-and-forth) motion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F806%2F1%2AbHTEGg6rqeQHbFe5yJRXRA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F806%2F1%2AbHTEGg6rqeQHbFe5yJRXRA.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  GridMap
&lt;/h1&gt;

&lt;p&gt;The GridMap node allows us to create 3D grid-based levels. With it, we can place our 3D models (tiles) on a grid interactively, similar to how TileMap works in 2D. If you have suitable models, you can use them to create, design, and manage large, repetitive environments like dungeons, cities, or landscapes.&lt;br&gt;&lt;br&gt;
The Gridmap is composed of cells. Each cell has the same dimensions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZ6n0kx9PW0v_eyh4axgWcQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZ6n0kx9PW0v_eyh4axgWcQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These cells are formed using floors (horizontal grid), and planes (vertical grid). Each floor represents a different height level, whereas each plane represents a different depth level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQYFktcix-LlKRGpeVgcxEw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQYFktcix-LlKRGpeVgcxEw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The GridMap uses a MeshLibrary Resource that contains an array of 3D tiles that can be placed on cells on the grid. Each tile is a mesh with materials, and it can also include optional collision and navigation shapes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUbT2QEAJJU8SvkZpLNaaLw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUbT2QEAJJU8SvkZpLNaaLw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my 3D base template project, you will see that my entire world was made using several GridMap nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F423%2F1%2AzDFVq2zEWetnw2olyOEtfA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F423%2F1%2AzDFVq2zEWetnw2olyOEtfA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADSPR0LvIPAVYOviaxNYV8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADSPR0LvIPAVYOviaxNYV8g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of these tiles that you see on the screen were originally .glb models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F524%2F1%2Awof36gZzj02DJZSKeduNlA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F524%2F1%2Awof36gZzj02DJZSKeduNlA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We add all of these models to a new scene, add whatever collisions we want, and then we convert this entire scene into MeshLibrary Resources so that they can be used by our GridMap as tiles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFd6tfW7_TnFXnR2-TR5lqA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFd6tfW7_TnFXnR2-TR5lqA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F572%2F1%2A-8KJ9_R0k-ufNLSf__N71g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F572%2F1%2A-8KJ9_R0k-ufNLSf__N71g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F521%2F1%2A2yBRLxo1VwzsWlZRpi7wpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F521%2F1%2A2yBRLxo1VwzsWlZRpi7wpg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F829%2F1%2A4gJebNZa97Rf1bv5C2aunw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F829%2F1%2A4gJebNZa97Rf1bv5C2aunw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Create a grid-based map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;To begin, we need a MeshLibrary, which is a collection of individual meshes that can be used in the GridMap.&lt;/li&gt;
&lt;li&gt;Create a new scene with a Node3D node as the root node. Rename this node to “GridTiles”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F557%2F1%2AT27UjntYx7NIwexfT_GCEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F557%2F1%2AT27UjntYx7NIwexfT_GCEQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import any .glb asset that you want to use, and then drag it into this new scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlxFgj8NHkqN4Cc4oxOW7KA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlxFgj8NHkqN4Cc4oxOW7KA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you added meshes that need to block the player or the player should be able to walk on it (such as the ground), you’ll have to localize these scenes and add a collision shape to them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F743%2F1%2AQqxRrM8fqlZF-XhqrKwyKQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F743%2F1%2AQqxRrM8fqlZF-XhqrKwyKQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F439%2F1%2A74z1Gz8dAlJfifFt6zuGvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F439%2F1%2A74z1Gz8dAlJfifFt6zuGvg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F554%2F1%2AteLbGGjb2dx_MRacvfJaSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F554%2F1%2AteLbGGjb2dx_MRacvfJaSQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After this is done, you can navigate to Scene &amp;gt; Export As and export this scene as a MeshLibrary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F561%2F1%2Asku_wZmsZu0GVMBgCmqFMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F561%2F1%2Asku_wZmsZu0GVMBgCmqFMA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5AAfwWbJLIjoZNqRfyx2jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5AAfwWbJLIjoZNqRfyx2jg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F520%2F1%2An0CAZesw28ZBRrEOOiEU9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F520%2F1%2An0CAZesw28ZBRrEOOiEU9A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can add these to a GridMap. In your Main scene, add a new GridMap node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F537%2F1%2AJPU3PiDKLyc6NqXIxL-pmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F537%2F1%2AJPU3PiDKLyc6NqXIxL-pmw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign the library that you just created as its MeshLibrary resource. The tiles should now be available to be placed down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsffRa8Qp1VGyKCb3SfmifA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsffRa8Qp1VGyKCb3SfmifA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your meshes look odd, you can change the cell size to fit your mesh, as well as disable centering on a certain axis so it “snaps” better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F707%2F1%2AnL-NYZXaBwiym3t-Bqr2yg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F707%2F1%2AnL-NYZXaBwiym3t-Bqr2yg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQcnUtVtDtpKEqvBvk3YPRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQcnUtVtDtpKEqvBvk3YPRw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can alter between floors and planes by pressing the C, X, and Z keys on your keyboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtqQgzDfgnd8ZSL-p8rE5pQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtqQgzDfgnd8ZSL-p8rE5pQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0QT3E2Nz7vNFV4HPDyKqEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0QT3E2Nz7vNFV4HPDyKqEQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuGIFj7q2E0QiKU08e0GL6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuGIFj7q2E0QiKU08e0GL6g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can delete tiles by hovering over them and holding down your &lt;strong&gt;right&lt;/strong&gt; mouse button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AG1QNKBjm9xqOct-b7f55HA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AG1QNKBjm9xqOct-b7f55HA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can rotate meshes via the D and S keys on your keyboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F869%2F1%2AzCQlzTGLmtw7_hfOCOiHcQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F869%2F1%2AzCQlzTGLmtw7_hfOCOiHcQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F802%2F1%2AeTxVp_s5TIWSYvyakxH9hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F802%2F1%2AeTxVp_s5TIWSYvyakxH9hg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F852%2F1%2Af5osS9dqDpWdyudcgZxV_Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F852%2F1%2Af5osS9dqDpWdyudcgZxV_Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F855%2F1%2A8vm1NmpYIFhyj25QHCb1CQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F855%2F1%2A8vm1NmpYIFhyj25QHCb1CQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will have to use multiple GridMaps with different settings to achieve a good result. Unless you’re using tiles that are all the same size, you won’t be able to do everything using only one GridMap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F363%2F1%2Aq5ZgCN6Rjutp-1b9jfTOHQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F363%2F1%2Aq5ZgCN6Rjutp-1b9jfTOHQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F495%2F1%2AZa4BHTKrllFwN1hm4jDKAw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F495%2F1%2AZa4BHTKrllFwN1hm4jDKAw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F489%2F1%2AH0KPbOclrFkUBG-KkLAmeg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F489%2F1%2AH0KPbOclrFkUBG-KkLAmeg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go ahead and create your mini world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6PtRUmu8R47aRupMMaa7xA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6PtRUmu8R47aRupMMaa7xA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run your scene and test your creation!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F822%2F1%2AhHn_LHziMo-NboUpEOw_zw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F822%2F1%2AhHn_LHziMo-NboUpEOw_zw.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Timer
&lt;/h1&gt;

&lt;p&gt;The Timer node is used to create countdown timers that can trigger events after a specified period. The Timer node provides several properties to control its behavior, including wait_time, autostart, and one_shot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;wait_time&lt;/strong&gt; : The duration in seconds that the timer will count down before emitting the timeout signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;autostart&lt;/strong&gt; : If set to true, the timer will start automatically when the scene is loaded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;one_shot&lt;/strong&gt; : If set to true, the timer will stop after emitting the timeout signal once. If false, the timer will restart automatically after each timeout.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It comes with a timeout signal, which is emitted when the timer reaches zero. This signal can be connected to a function to perform specific actions when the timer completes its countdown. The timeout signal is a crucial part of the Timer node's functionality, allowing you to trigger events at precise intervals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mechanic:
&lt;/h4&gt;

&lt;p&gt;Spawn an enemy every 5 seconds.&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Add a Timer node to your scene. Set its wait_time to 5 seconds. Since we want the enemy to “spawn” as soon as the game loads, we should enable its autostart property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F351%2F1%2AsiTDir0quHSj4WwJcxBquQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F351%2F1%2AsiTDir0quHSj4WwJcxBquQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F501%2F1%2AdRQl052lJst_pl0nbWwPxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F501%2F1%2AdRQl052lJst_pl0nbWwPxQ.png" alt="Book of Nodes" width="501" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect the timer node’s timeout signal to your script. This will execute our logic to spawn our enemy every 5 seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F938%2F1%2Agjy0H078FKlypI2EY3G1fA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F938%2F1%2Agjy0H078FKlypI2EY3G1fA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your code, let’s “spawn” an enemy. Since we don’t have an actual enemy scene, we will just print the amount of enemies we have spawned.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Main.gd

extends Node3D

@onready var timer = $Timer
var enemy_count = 0

func _ready():
 if not timer.is_stopped():
  timer.start()

func _on_timer_timeout():
 spawn_enemy()

func spawn_enemy():
 enemy_count += 1
 print("An enemy has spawned!")
 print("Current enemy count: ", enemy_count) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run your game and your enemy should spawn each time the timer reaches 0!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aswh8PGWB5nOLpGF765Pd_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aswh8PGWB5nOLpGF765Pd_w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>guide</category>
      <category>godot</category>
      <category>3d</category>
    </item>
    <item>
      <title>The Book of Nodes: UI</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Wed, 07 Aug 2024 12:43:46 +0000</pubDate>
      <link>https://forem.com/christinec_dev/the-book-of-nodes-ui-igb</link>
      <guid>https://forem.com/christinec_dev/the-book-of-nodes-ui-igb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below you can find a list of UI nodes that can be used in Godot 4. This is part of my &lt;a href="https://dev.to/christinec_dev/the-book-of-nodes-1p9c"&gt;Book of Nodes&lt;/a&gt; series. If you want to see similar content on 2D or 3D nodes, please refer to the parent page of this post for those links. 😊&lt;/p&gt;

&lt;p&gt;Before we begin, if you need a base project to test these code snippets, feel free to download my FREE 2D and 3D templates &lt;a href="https://christinecdevs.site/2d-3d-prototype-templates/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I’ll be using these templates throughout this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*Please note that this list is NOT 100% complete yet, but I will be updating this list as time goes on.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Control&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CanvasLayer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CanvasModulate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Container&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HBoxContainer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VBoxContainer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GridContainer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ColorRect&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Panel&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Button&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Label&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RichTextLabel&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ProgressBar&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Common Properties
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Anchoring
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Determines how a UI element is positioned and resized relative to its parent container.&lt;/li&gt;
&lt;li&gt;anchor_left: Sets the left anchor point (0 to 1).&lt;/li&gt;
&lt;li&gt;anchor_top: Sets the top anchor point (0 to 1).&lt;/li&gt;
&lt;li&gt;anchor_right: Sets the right anchor point (0 to 1).&lt;/li&gt;
&lt;li&gt;anchor_bottom: Sets the bottom anchor point (0 to 1).&lt;/li&gt;
&lt;li&gt;full_rect: Sets the anchor point to all sides.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Margins
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Defines the distance between the UI element and its parent container’s edges.&lt;/li&gt;
&lt;li&gt;margin_left: Distance from the left edge.&lt;/li&gt;
&lt;li&gt;margin_top: Distance from the top edge.&lt;/li&gt;
&lt;li&gt;margin_right: Distance from the right edge.&lt;/li&gt;
&lt;li&gt;margin_bottom: Distance from the bottom edge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Font
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customizes the appearance of text within UI elements.&lt;/li&gt;
&lt;li&gt;font: The font resource used for the text.&lt;/li&gt;
&lt;li&gt;font_size: The size of the font.&lt;/li&gt;
&lt;li&gt;font_color: The color of the font.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Color
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customize the color properties of UI elements.&lt;/li&gt;
&lt;li&gt;color: The main color of the UI element.&lt;/li&gt;
&lt;li&gt;font_color: The color of the text.&lt;/li&gt;
&lt;li&gt;modulate: The alpha value applied to the UI element.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Transform
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Controls the position, rotation, and scale of UI elements.&lt;/li&gt;
&lt;li&gt;position: The position of the UI element.&lt;/li&gt;
&lt;li&gt;rotation: The rotation of the UI element in degrees.&lt;/li&gt;
&lt;li&gt;scale: The scale of the UI element.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Size Flags
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Determines how a UI element resizes within its parent container.&lt;/li&gt;
&lt;li&gt;size_flags_horizontal: Horizontal resizing behavior (e.g., fill, expand).&lt;/li&gt;
&lt;li&gt;size_flags_vertical: Vertical resizing behavior (e.g., fill, expand).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Visibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Controls the visibility of UI elements.&lt;/li&gt;
&lt;li&gt;visible: Whether the UI element is visible.&lt;/li&gt;
&lt;li&gt;self_modulate: The color modulation applied to the UI element, affecting its visibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Focus
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Manages keyboard and controller focus for UI elements.&lt;/li&gt;
&lt;li&gt;focus_mode: Determines if the UI element can receive focus (none, click, all).&lt;/li&gt;
&lt;li&gt;focus_neighbour_*: Specifies neighboring UI elements for focus navigation (up, down, left, right).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tooltip
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Provides additional information when the user hovers over a UI element.&lt;/li&gt;
&lt;li&gt;hint_tooltip: The text displayed as a tooltip.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Theme Overrides
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Allows customization of the UI element’s appearance beyond the default theme.&lt;/li&gt;
&lt;li&gt;theme: The theme resource applied to the UI element.&lt;/li&gt;
&lt;li&gt;theme_type_variation: A variation of the theme type for more specific customization.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Control
&lt;/h2&gt;

&lt;p&gt;A Control node provides a bounding rectangle on the viewport that can be used for creating user interfaces in Godot, as they handle input events, focus, and other UI-specific functionalities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Drag and drop a sprite on the map.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a Control node to your scene. This represents the item you will drag and drop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4v70n1mm0k7ggn9uh0af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4v70n1mm0k7ggn9uh0af.png" alt="Book of Nodes" width="424" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We need to visualize it, so add a TextureRect node to it. This node allows us to add a sprite to the control so that we can see what we are moving. This works better than the Sprite2D/3D node because it can be anchored to our Control container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1t50j28yznvmwll3vmq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1t50j28yznvmwll3vmq.png" alt="Book of Nodes" width="431" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add any texture (icon) to this TextureRect.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtbe5w74f80zadipwwvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtbe5w74f80zadipwwvo.png" alt="Book of Nodes" width="258" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4kjeiggllw00hlw6cgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4kjeiggllw00hlw6cgi.png" alt="Book of Nodes" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach a script to your Control node. To be able to drag and drop this object, we will need to connect its gui_input signal to our script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gmnzr5h02wldemprxju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gmnzr5h02wldemprxju.png" alt="Book of Nodes" width="731" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your code, add the functionality to select the item using the LEFT mouse button. Use set_drag_preview to show a visual representation of the item being dragged.&lt;/li&gt;
&lt;li&gt;Then, add the functionality to drop your item on the LEFT mouse button release.&lt;/li&gt;
&lt;li&gt;And then also add the functionality to snap the item to your mouse cursor whilst dragging it around.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;### Control.gd
&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Control&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;drag_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZERO&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;is_dragging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_gui_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;InputEventMouseButton&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;button_index&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;MOUSE_BUTTON_LEFT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Select
&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;is_dragging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;get_viewport&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;gui_is_dragging&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;set_drag_preview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="c1"&gt;# Drop
&lt;/span&gt;   &lt;span class="n"&gt;is_dragging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;
 &lt;span class="c1"&gt;# Drag
&lt;/span&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;InputEventMouseMotion&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;is_dragging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;global_pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_global_mouse_position&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;global_position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global_pos&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Test your logic by selecting the item and dragging it around.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2h4oisfiwxz9d178qoi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2h4oisfiwxz9d178qoi.gif" alt="Book of Nodes" width="600" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CanvasLayer
&lt;/h2&gt;

&lt;p&gt;A CanvasLayer is used for independent rendering of objects within a 2D scene, often for UI elements or HUDs. It renders its child nodes independently of the main scene's camera, which means that they remain fixed on the screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;HUD (Heads-Up Display).&lt;/li&gt;
&lt;li&gt;Fixed-position UI elements.&lt;/li&gt;
&lt;li&gt;Overlay menus.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;To demonstrate the use of the layer property, we will create a simple scene with two CanvasLayer nodes. One will be used for a background layer, and the other for a UI layer. The background layer will be drawn behind the UI layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add two CanvasLayernodes to your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7wkig93czfjlb23pn3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7wkig93czfjlb23pn3b.png" alt="Book of Nodes" width="430" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a Label node to the first CanvasLayer node. Add a ColorRect to the second CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi65qonollcvn9276xnzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi65qonollcvn9276xnzg.png" alt="Book of Nodes" width="579" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give the Label some text, and change the ColorRects color to a dark grey. Also, change its anchor-preset to be full_rect.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5mijmz98xwp38g1m1os.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5mijmz98xwp38g1m1os.png" alt="Book of Nodes" width="261" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fciwv8jci5gv4e5blj3m7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fciwv8jci5gv4e5blj3m7.png" alt="Book of Nodes" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will see that our label isn’t showing, because our first CanvasLayer node has the same Layer value as the second CanvasLayer.&lt;/li&gt;
&lt;li&gt;Change the first CanvasLayer node’s Layer value to be “2”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmh6q0dmlj0pl5tsa03kv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmh6q0dmlj0pl5tsa03kv.png" alt="Book of Nodes" width="488" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your label should now be on top of the background!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tl1v9koi5mcxfeere1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tl1v9koi5mcxfeere1b.png" alt="Book of Nodes" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Container
&lt;/h2&gt;

&lt;p&gt;A Container is used to organize UI elements, providing a base class for various container types. It inherits from Control and provides functionality for arranging child nodes. We usually don’t use this node a lot, as a normal Control node suffices.&lt;/p&gt;

&lt;p&gt;You might, however, use a ScrollContainer node. A ScrollContainer is a type of container node in Godot that provides scrollbars to its child control when needed. It is useful for creating scrollable areas in your UI, such as lists, text areas, or any content that exceeds the visible area of the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Base class for custom container types.&lt;/li&gt;
&lt;li&gt;Organizing complex UI layouts.&lt;/li&gt;
&lt;li&gt;Creating custom layout behaviors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvabad2sgegp5gaj29i7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvabad2sgegp5gaj29i7m.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HBoxContainer
&lt;/h2&gt;

&lt;p&gt;An HBoxContainer is used to arrange UI elements horizontally. It inherits from Container and arranges its children in a horizontal line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Horizontal menus.&lt;/li&gt;
&lt;li&gt;Toolbars.&lt;/li&gt;
&lt;li&gt;Row-based layouts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bebnhq7xkhdi5ssrnic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bebnhq7xkhdi5ssrnic.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Arrange a list of items horizontally on the scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a Control node to your scene. This will hold our HBoxContainer. Change its size to something like 600px by 600px to give it a bounding area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sofnb6yniqxypqdc968.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sofnb6yniqxypqdc968.png" alt="Book of Nodes" width="485" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvvpis34h14r1iu7yem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvvpis34h14r1iu7yem.png" alt="Book of Nodes" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a HboxContainer node to this Control node. Also, make sure its anchor preset is full_rect so that it takes up the entire space provided by the Control node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrzchak3whd3ufsa9xpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrzchak3whd3ufsa9xpd.png" alt="Book of Nodes" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add three Label nodes to the HBoxContainer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fn2h5kjv1xli3qdr15f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fn2h5kjv1xli3qdr15f.png" alt="Book of Nodes" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will see that the items stack next to each other, but they don’t take up the entire space. To fix this, we will need to set their container sizing properties to fill and expand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fduss5kchyww3xxj0fq46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fduss5kchyww3xxj0fq46.png" alt="Book of Nodes" width="483" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now your labels will be arranged horizontally across the entire 600px by 600px boundary box!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkl8wwi9919squur77w8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkl8wwi9919squur77w8a.png" alt="Book of Nodes" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To add some spacing between the items, select the HBoxContainer node, and change its separation constant to a value such as 10.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1q8v0wsyxazcdm51d74c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1q8v0wsyxazcdm51d74c.png" alt="Book of Nodes" width="475" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35ywzmusi0k7z1x60u3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35ywzmusi0k7z1x60u3r.png" alt="Book of Nodes" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VBoxContainer
&lt;/h2&gt;

&lt;p&gt;A VBoxContainer is used to arrange UI elements vertically. It inherits from Container and arranges its children in a vertical line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vertical settings menus.&lt;/li&gt;
&lt;li&gt;Stacked buttons.&lt;/li&gt;
&lt;li&gt;Column-based layouts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F015f9abepi2gtxit06x1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F015f9abepi2gtxit06x1.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Arrange a list of items vertically on the scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a Control node to your scene. This will hold our VBoxContainer. Change its size to something like 600px by 600px to give it a bounding area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sofnb6yniqxypqdc968.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sofnb6yniqxypqdc968.png" alt="Book of Nodes" width="485" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvvpis34h14r1iu7yem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvvpis34h14r1iu7yem.png" alt="Book of Nodes" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a VboxContainer node to this Control node. Also, make sure its anchor preset is full_rect so that it takes up the entire space provided by the Control node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs49tci47v6qj1fcng4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs49tci47v6qj1fcng4d.png" alt="Book of Nodes" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add three Label nodes to the VBoxContainer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmplh00of74hl5iin99w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmplh00of74hl5iin99w.png" alt="Book of Nodes" width="797" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will see that the items stack on top of each other, but they don’t take up the entire space. To fix this, we will need to set their container sizing properties to fill and expand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fduss5kchyww3xxj0fq46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fduss5kchyww3xxj0fq46.png" alt="Book of Nodes" width="483" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now your labels will be arranged horizontally across the entire 600px by 600px boundary box!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cerrh2gxl4rn50koqqf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cerrh2gxl4rn50koqqf.png" alt="Book of Nodes" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To add some spacing between the items, select the VBoxContainer node, and change its separation constant to a value such as 10.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhf634xgtd5i1toytqjem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhf634xgtd5i1toytqjem.png" alt="Book of Nodes" width="489" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuca0lmyjkg5kzsfd02j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuca0lmyjkg5kzsfd02j.png" alt="Book of Nodes" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GridContainer
&lt;/h2&gt;

&lt;p&gt;A GridContainer is used to arrange UI elements in a grid. It inherits from Container and arranges its children in a grid layout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keypads.&lt;/li&gt;
&lt;li&gt;Control panels.&lt;/li&gt;
&lt;li&gt;Inventory grids.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffq9pammunjruv7do6mdd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffq9pammunjruv7do6mdd.png" alt="Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Arrange a list of items in a grid on the scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a Control node to your scene. This will hold our GridContainer. Change its size to something like 600px by 600px to give it a bounding area.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sofnb6yniqxypqdc968.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0sofnb6yniqxypqdc968.png" alt="Book of Nodes" width="485" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvvpis34h14r1iu7yem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakvvpis34h14r1iu7yem.png" alt="Book of Nodes" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a GridContainer node to this Control node. Also, make sure its anchor preset is full_rect so that it takes up the entire space provided by the Control node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv1yx3mua5qxfi5ri3rl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv1yx3mua5qxfi5ri3rl2.png" alt="Book of Nodes" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add fourLabel nodes to the GridContainer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1qtxdiuc4y9jsinpmxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1qtxdiuc4y9jsinpmxu.png" alt="Book of Nodes" width="707" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will see that the items stack on top of each other, instead of in a grid. To fix this, we will need to up our columns property in our GridContainer node. Change this value to 2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjuwbz1yu3oq6vd8871e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjuwbz1yu3oq6vd8871e.png" alt="Book of Nodes" width="485" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ku0xx02oz04exye5rcv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ku0xx02oz04exye5rcv.png" alt="Book of Nodes" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now they are arranged in the grid, but they don’t take up the entire space. To fix this, we will need to set their container sizing properties to fill and expand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzsejxpmwbck7gda4orx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzsejxpmwbck7gda4orx.png" alt="Book of Nodes" width="481" height="828"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now your labels will be arranged in a grid format across the entire 600px by 600px boundary box!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyize9newy8ghsw5i9s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyize9newy8ghsw5i9s4.png" alt="Book of Nodes" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To add some spacing between the items, select the GridContainer node, and change its separation constant to a value such as 10.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy72moh28shjovq37gbh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy72moh28shjovq37gbh7.png" alt="Book of Nodes" width="490" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffagc1316w11fyu74jml3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffagc1316w11fyu74jml3.png" alt="Book of Nodes" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ColorRect
&lt;/h2&gt;

&lt;p&gt;A ColorRect is used to display a solid color rectangle, often for backgrounds or color overlays. It inherits from Control and provides a simple way to display a rectangle filled with a specified color. The color can be set and changed dynamically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Case:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Background overlays.&lt;/li&gt;
&lt;li&gt;Progress bars.&lt;/li&gt;
&lt;li&gt;Color indicators.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fordda677fxhavu0388qa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fordda677fxhavu0388qa.png" alt="Book of Nodes" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Add a background color to your scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasLayer node to your scene. This will ensure that our ColorRect is drawn on our UI, so it can be displayed in the background.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6o4rg4jnsslq88kfsso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6o4rg4jnsslq88kfsso.png" alt="Book of Nodes" width="424" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a ColorRectnode to your CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvgdbzpk4j3cqjyha2j4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvgdbzpk4j3cqjyha2j4.png" alt="Book of Nodes" width="417" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change its color, and change its anchor preset to be full_rect so that it takes up the entire screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55u6upgh7zat5yg3bk5y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55u6upgh7zat5yg3bk5y.png" alt="Book of Nodes" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the CanvasLayer node’s layer property to something like -1 so that it is displayed behind our other nodes. We should now have a background color!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcstds5i32o51ydsgyoz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcstds5i32o51ydsgyoz.png" alt="Book of Nodes" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Panel
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Panel is used to create a panel for grouping UI elements, providing a background and border. It inherits from Control and provides a simple way to group and visually separate UI elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Use Case:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Settings panels.&lt;/li&gt;
&lt;li&gt;Dialog boxes.&lt;/li&gt;
&lt;li&gt;Grouping related UI elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrb0xbvwelh7d6bas7hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrb0xbvwelh7d6bas7hw.png" alt="Book of Nodes" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Add a background color to your scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasLayer node to your scene. This will ensure that our Panel is drawn on our UI, so it can be displayed in the background.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6o4rg4jnsslq88kfsso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6o4rg4jnsslq88kfsso.png" alt="Book of Nodes" width="424" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a Panel node to your CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vepxslho0f9fjuossgr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vepxslho0f9fjuossgr.png" alt="Book of Nodes" width="425" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To change its color, we’ll need to give it a new theme style of type StyleBoxFlat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6k6rg73nge8b8z1m8zu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6k6rg73nge8b8z1m8zu.png" alt="Book of Nodes" width="497" height="930"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we can give it a new color, border, and even a shadow!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwka7zdlowvqzfquwhdkz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwka7zdlowvqzfquwhdkz.png" alt="Book of Nodes" width="492" height="903"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change its anchor preset to full_rect so that it takes up the entire screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6iuf3j8e602wv410plg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6iuf3j8e602wv410plg.png" alt="Book of Nodes" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the CanvasLayer node’s layer property to something like -1 so that it is displayed behind our other nodes. We should now have a background color!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvi6x19zto94gk9k687r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvi6x19zto94gk9k687r.png" alt="Book of Nodes" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CanvasModulate
&lt;/h2&gt;

&lt;p&gt;A CanvasModulate applies a color tint to all nodes on a canvas. It tints the canvas elements using its assigned color.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Night mode effect.&lt;/li&gt;
&lt;li&gt;Global color adjustments.&lt;/li&gt;
&lt;li&gt;Visual effects for different game states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A3FyNxwWMqdHtO7Vn" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A3FyNxwWMqdHtO7Vn" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A7Egm282il7wWjlas" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A7Egm282il7wWjlas" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Add a day-and-night cycle to your game&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasModulatenode to your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnl0l0dqb8pdi11xa5plq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnl0l0dqb8pdi11xa5plq.png" alt="Book of Nodes" width="429" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you change its color property, the entire scene's color should change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4z875mg0bsc493poqc4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4z875mg0bsc493poqc4.png" alt="Book of Nodes" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We want to animate this property. So, add an AnimationPlayer node to your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ovabl7de10ol98mswgz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ovabl7de10ol98mswgz.png" alt="Book of Nodes" width="419" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new animation called day_night_cycle. Set the length of this animation to be 24 seconds long. This will make our day 24 seconds long (for 24 hours).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F980%2F1%2AUpfSE5-CFxcMyUkhFtIM0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F980%2F1%2AUpfSE5-CFxcMyUkhFtIM0g.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F980%2F1%2A_euiR-wDIQhiNhabZzFkTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F980%2F1%2A_euiR-wDIQhiNhabZzFkTg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also, enable looping.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F980%2F1%2AfByYZ3uU17ItcUSIfJp4iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F980%2F1%2AfByYZ3uU17ItcUSIfJp4iw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now add a color keyframe for every 6 hours (or whatever preference you have). These colors should represent the colors from 0 AM to 24 PM.&lt;/li&gt;
&lt;li&gt;On my timeline, my colors are:
&lt;strong&gt;0:&lt;/strong&gt; #0f0a49
&lt;strong&gt;6:&lt;/strong&gt; #7b5436
&lt;strong&gt;12:&lt;/strong&gt; #ffffff
&lt;strong&gt;18:&lt;/strong&gt; #5b6a99
*&lt;em&gt;24: *&lt;/em&gt; #0f0a49&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ap8S3D_9wwxiXBlKVITqr-w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ap8S3D_9wwxiXBlKVITqr-w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now when we run our game, we should play this animation.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;### Main.gd
&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="nd"&gt;@onready&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;animation_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimationPlayer&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="n"&gt;animation_player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;day_night_cycle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AgebUaLjGpqh3qIFy1deCTQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AgebUaLjGpqh3qIFy1deCTQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want a better tutorial using shaders, check out the video on my &lt;a href="https://github.com/christinec-dev/DayNightCycleGodot" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Button
&lt;/h2&gt;

&lt;p&gt;A Button is used to create a clickable button for user interactions. It inherits from BaseButton and provides functionality for detecting clicks and triggering actions.&lt;/p&gt;

&lt;p&gt;If you want to use a button that has a texture (image) and more customizability, you should use a TextureButton node. The TextureButton node is a button that uses textures for its different states (normal, pressed, hover, etc.) instead of the default theme. This allows for more customized and visually appealing buttons. It inherits from BaseButton and provides properties to set textures for different states.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Interactive buttons.&lt;/li&gt;
&lt;li&gt;Menu options.&lt;/li&gt;
&lt;li&gt;Form submissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AarehKRAxyLNLhfRR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AarehKRAxyLNLhfRR.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Add a clickable button to your scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasLayer node to your scene. This will ensure that our Buttonis drawn on our UI, so it can be displayed at all times.&lt;/li&gt;
&lt;li&gt;Add a Button node to your CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F931%2F1%2AtSx_LMaB5aXezm5K33X2lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F931%2F1%2AtSx_LMaB5aXezm5K33X2lg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you run your scene, your Button should be visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2As2rSvfSgEgrzYMVvYrBZfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2As2rSvfSgEgrzYMVvYrBZfg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, attach its pressed() signal function to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F874%2F1%2ABIhUmBphAPK4_7r_0hsulQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F874%2F1%2ABIhUmBphAPK4_7r_0hsulQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If we press the button, we will change its text. We will keep track of the times we’ve pressed it and update it each time we press the button.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;### Main.gd
&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="nd"&gt;@onready&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;CanvasLayer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Button&lt;/span&gt;

&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;button_pressed_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_button_pressed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="n"&gt;button_pressed_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
 &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ve pressed me: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;button_pressed_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; times!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Every time you press the button, the count should update!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F649%2F1%2AfZh-W7hhcmNQ5o1Y_j6yyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F649%2F1%2AfZh-W7hhcmNQ5o1Y_j6yyA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F677%2F1%2AwQWoG1PNHxSM2QbTYpUQGQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F677%2F1%2AwQWoG1PNHxSM2QbTYpUQGQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F671%2F1%2AI8UbElRmgVaPdoTpsOXbUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F671%2F1%2AI8UbElRmgVaPdoTpsOXbUw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Label
&lt;/h2&gt;

&lt;p&gt;A Label is used to display text. It inherits from Control and provides functionality for displaying text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Static text display.&lt;/li&gt;
&lt;li&gt;Descriptive labels.&lt;/li&gt;
&lt;li&gt;Titles and headings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AEn_IPRdJfycwj55w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AEn_IPRdJfycwj55w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Add a label that changes its text when you hover over it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasLayer node to your scene. This will ensure that our Label is drawn on our UI, so it can be displayed at all times.&lt;/li&gt;
&lt;li&gt;Add a Labelnode to your CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKvLDNdTqmYEjheK3O1va3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKvLDNdTqmYEjheK3O1va3w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you run your scene, your Label should be visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AhDBP26J3WdiRHOdhF2PhwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AhDBP26J3WdiRHOdhF2PhwA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, let’s make it more visible. Change its font color to be red, and its size to something like 25px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOkyPYwtQ-9pqCZA6tRl79w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOkyPYwtQ-9pqCZA6tRl79w.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since we want it to detect mouse events, we need to change its Mouse Filter mode to Pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F411%2F1%2A5jJPEko-18ioWksrHjwyRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F411%2F1%2A5jJPEko-18ioWksrHjwyRw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, to detect that we are hovering over it, we need to attach its mouse_entered() and mouse_exited() signals to our script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F879%2F1%2Ak9d2c41tohL6tdW70TpKyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F879%2F1%2Ak9d2c41tohL6tdW70TpKyA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, simply change the text when we enter and exit the label while hovering! If you run your game, the label should change depending on whether or not you are hovering over it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;### Main.gd
&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="nd"&gt;@onready&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;CanvasLayer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_label_mouse_entered&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re hovering over a label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_label_mouse_exited&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re away from the label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Akafn21XKTX_23bks9oWTiA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Akafn21XKTX_23bks9oWTiA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuyJ4hJgEK_q9EwDdgD43TQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuyJ4hJgEK_q9EwDdgD43TQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2pmNQ1WPUtxS71Q-b1HuQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2pmNQ1WPUtxS71Q-b1HuQg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RichTextLabel
&lt;/h2&gt;

&lt;p&gt;A RichTextLabel is used to display formatted text. It inherits from Control and provides functionality for displaying rich text with formatting, such as bold, italics, and images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Formatted text display.&lt;/li&gt;
&lt;li&gt;Dialogue boxes.&lt;/li&gt;
&lt;li&gt;Instructional text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AufXPEXpSU1N07oE9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AufXPEXpSU1N07oE9.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Write words in a typewriter effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasLayer node to your scene. This will ensure that our RichTextLabelis drawn on our UI, so it can be displayed at all times.&lt;/li&gt;
&lt;li&gt;Add a RichTextLabel node to your CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F569%2F1%2A562GwtEqVa8vSqi4DKQ-rA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F569%2F1%2A562GwtEqVa8vSqi4DKQ-rA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change its size to something like 200px by 200px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F420%2F1%2Ajqw7gbuWfmtHDLiksueY7A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F420%2F1%2Ajqw7gbuWfmtHDLiksueY7A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you run your scene, your RichTextLabel should be visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AszA7hmOecj_peHIiQw2Swg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AszA7hmOecj_peHIiQw2Swg.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, let’s make it more visible. Change its font color to red, and its size to something like 25px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArozEOh1IUg0o8ymor1Q8IQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArozEOh1IUg0o8ymor1Q8IQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To create our typewriter animation, we will need to use an AnimationPlayer node. Add this node to your scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F570%2F1%2APpWcE540uo5fHiM3S5ketw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F570%2F1%2APpWcE540uo5fHiM3S5ketw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new animation called typewriter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2AfYrT9XDOIR0kPcvUosyeIA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2AfYrT9XDOIR0kPcvUosyeIA.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To create a typewriter effect, we need to animate our RichTextLabel node’s visible ratio property, which defines how much of our text is visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtIs7T60q4Kx0JiIMHAgzog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AtIs7T60q4Kx0JiIMHAgzog.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ao3sgYSKDbwxu4IvusATefQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ao3sgYSKDbwxu4IvusATefQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the 0 keyframe mark, set your visible ratio to be equal to 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Akb2gCmCbVusoyVi4njp98Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Akb2gCmCbVusoyVi4njp98Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the 1 keyframe mark, set your visible ratio to be equal to 1. This means in 1 second, our text will go from no characters to full characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABEkEVebi418VbDBCTD7Lrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABEkEVebi418VbDBCTD7Lrw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now if you play your animation, your text should play as if it's being typed out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AB2j89MdBCuQcJN1FZx7FBQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AB2j89MdBCuQcJN1FZx7FBQ.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ProgressBar
&lt;/h2&gt;

&lt;p&gt;ProgressBar is a UI element that visually represents a value within a range. It inherits from the Range class, which provides properties like min_value, max_value, and value to control the progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Loading screens.&lt;/li&gt;
&lt;li&gt;Health bars.&lt;/li&gt;
&lt;li&gt;Progress indicators.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mechanic:
&lt;/h3&gt;

&lt;p&gt;Create a health bar that increases every 1 second, and when we press SPACE, it decreases in value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a CanvasLayer node to your scene. This will ensure that our ProgressBar node is drawn on our UI, so it can be displayed at all times.&lt;/li&gt;
&lt;li&gt;Add a ProgressBarnode to your CanvasLayer node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F325%2F1%2AcwlTYJob7zexNHYDiFIBSw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F325%2F1%2AcwlTYJob7zexNHYDiFIBSw.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change its size to something like 200px by 27px, and enable its Rounded value so it only shows whole numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AL0eipvmZ0tulvGXYQ6A72Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AL0eipvmZ0tulvGXYQ6A72Q.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To be able to increase our ProgressBar, we should add a Timer node. Enable this timer node’s autostart property, and connect its timeout signal to your script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F330%2F1%2AAFBtBBvJPKpBFvT4Er79TQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F330%2F1%2AAFBtBBvJPKpBFvT4Er79TQ.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F479%2F1%2Av9haZ7FZuVHVbv6zTGxB4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F479%2F1%2Av9haZ7FZuVHVbv6zTGxB4A.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F946%2F1%2ADD-_BX_PEWzedwipYHNbng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F946%2F1%2ADD-_BX_PEWzedwipYHNbng.png" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whenever it times out (every 1 second its active), we will increase our “health” value.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;### Main.gd
&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="nd"&gt;@onready&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;progress_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;CanvasLayer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ProgressBar&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_timer_timeout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="n"&gt;progress_bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Whenever we press our SPACE bar, we should decrease our health value.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;### Main.gd
&lt;/span&gt;
&lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="nd"&gt;@onready&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;progress_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;CanvasLayer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ProgressBar&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_timer_timeout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="n"&gt;progress_bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_action_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ui_accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;progress_bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now if we run our scene, our health should increase every second, but decrease when we press our button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2Arr3wN4aaGVxU4e0FWGiXKw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2Arr3wN4aaGVxU4e0FWGiXKw.gif" alt="Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>3d</category>
      <category>godot</category>
      <category>node</category>
    </item>
    <item>
      <title>The Book of Nodes</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Wed, 07 Aug 2024 12:43:23 +0000</pubDate>
      <link>https://forem.com/christinec_dev/the-book-of-nodes-1p9c</link>
      <guid>https://forem.com/christinec_dev/the-book-of-nodes-1p9c</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbysoyl48lt1dkvl02grk.png" alt="The Book of Nodes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever delved into the Godot Documentation, you likely noticed two things: first, there is an abundance of nodes (many of which you might never use), and second, some of these nodes can be quite confusing.&lt;/p&gt;

&lt;p&gt;As a beginner Godot developer, understanding the purpose of each node can be confusing. Even as a somewhat seasoned Godot creator, I am still learning about new nodes and methods of doing things to this day. For example, when I first started learning Godot, I used a ColorRect node for all my UI backgrounds. However, this meant that if I wanted a background with a border, I had to use multiple ColorRects to achieve this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fproxy%2F1%2AxrBSbF0FO2F0ruZkGaM7IQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fproxy%2F1%2AxrBSbF0FO2F0ruZkGaM7IQ.png" alt="The Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: Using ColorRects to create a box with a border and a shadow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Later on, I discovered the Panel node, which offers a lot more customization, built-in borders, and even rounded corners! Although I still use ColorRects, I now know that there are better nodes (like the Panel node) that I can use to achieve the same result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fproxy%2F1%2AWV17Q0b2fwkLp2n-4LyvxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fproxy%2F1%2AWV17Q0b2fwkLp2n-4LyvxQ.png" alt="The Book of Nodes" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: Using a Panel to create a box with a border, curved corners, and a shadow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s why I wanted to create an encyclopedia of sorts, focusing on the most essential nodes to know as a beginner. I also want to give a big thanks to Robert at &lt;a href="https://sites.google.com/view/game-dev-guide/home?authuser=0" rel="noopener noreferrer"&gt;GameDev Journey&lt;/a&gt; for suggesting this idea, as the “Know Your Nodes” concept originally came from him.&lt;/p&gt;

&lt;p&gt;Now, to complete this encyclopedia, I’ve decided to organize the content into three distinct &lt;strong&gt;categories&lt;/strong&gt; : 2D, 3D, and UI. Within each category, you’ll find a list of &lt;strong&gt;nodes&lt;/strong&gt; relevant to that section. For each node, I will cover the &lt;strong&gt;mechanics&lt;/strong&gt; that can be implemented using this node, along with basic examples of how this mechanic can be &lt;strong&gt;implemented&lt;/strong&gt; into a project. This ensures that you not only learn about each node’s functionality but also how they can be practically applied during your game development process.&lt;/p&gt;

&lt;p&gt;Before we begin, if you need a base project to test these code snippets, feel free to download my FREE 2D and 3D templates &lt;a href="https://christinecdevs.site/2d-3d-prototype-templates/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I’ll be using these templates throughout this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*Please note that this list is not 100% complete yet, but I will be updating this list as time goes on.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Categories:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/christinec_dev/the-book-of-nodes-2d-3dkg"&gt;2D Nodes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/christinec_dev/the-book-of-nodes-3d-3f9n"&gt;3D Nodes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/christinec_dev/the-book-of-nodes-ui-3oao"&gt;UI Nodes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  UPDATE:
&lt;/h2&gt;

&lt;p&gt;Get your copy of My Book of Nodes for Godot 4 in an offline PDF format (and Word for GIF previews) now! &lt;/p&gt;

&lt;p&gt;In the offline version, all the categories (2D, 3D, and UI) are combined in a single document. No more waiting for my websites and blogs to load - take the content with you and access it instantly, wherever you are.&lt;/p&gt;

&lt;p&gt;Check it out, it's free. 😊&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/s/e9f19e30ff" rel="noopener noreferrer"&gt;https://ko-fi.com/s/e9f19e30ff&lt;/a&gt;&lt;/p&gt;




</description>
      <category>node</category>
      <category>godot</category>
    </item>
    <item>
      <title>Godot 2D &amp; 3D Prototype Templates</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Mon, 05 Aug 2024 12:25:03 +0000</pubDate>
      <link>https://forem.com/christinec_dev/godot-2d-3d-prototype-templates-al0</link>
      <guid>https://forem.com/christinec_dev/godot-2d-3d-prototype-templates-al0</guid>
      <description>&lt;p&gt;I have created templates for my Godot 2D and 3D projects on YouTube and KoFi. These templates are designed for prototyping and developing systems in Godot. They make it easier for us because we no longer have to build everything from scratch! 😊&lt;/p&gt;

&lt;p&gt;The 2D template contains a basic top-down character and a map, and the entire project template was created by me with the help of the following assets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://seliel-the-shaper.itch.io/character-base" rel="noopener noreferrer"&gt;https://seliel-the-shaper.itch.io/character-base&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quintino-pixels.itch.io/assorted-icons" rel="noopener noreferrer"&gt;https://quintino-pixels.itch.io/assorted-icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cupnooble.itch.io/sprout-lands-asset-pack" rel="noopener noreferrer"&gt;https://cupnooble.itch.io/sprout-lands-asset-pack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 3D template contains a basic third-person character and a map, and the entire project was created by me with the help of the following assets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://godotshaders.com/shader/stylized-sky/%20" rel="noopener noreferrer"&gt;https://godotshaders.com/shader/stylized-sky/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kenney.nl/assets/category:3D?sort=update" rel="noopener noreferrer"&gt;https://kenney.nl/assets/category:3D&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://godotengine.org/asset-library/asset/1815%20" rel="noopener noreferrer"&gt;https://godotengine.org/asset-library/asset/1815&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3D Preview:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pkxmr4qv7xs0xc95wks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pkxmr4qv7xs0xc95wks.png" alt="3D Preview 1" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2ACo1QtOHK_J70GDMo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2ACo1QtOHK_J70GDMo.png" alt="3D Preview 2" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2D Preview:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2ALPvNjGKMwZANon7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2ALPvNjGKMwZANon7i.png" alt="2D Preview 1" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2AaHYKNddyKH-XBO5P.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1000%2F0%2AaHYKNddyKH-XBO5P.png" alt="2D Preview 2" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can download these projects for free on my KoFi page. They are not available on GitHub because the file size was too large to upload. You don’t need to pay to use them!&lt;/p&gt;

&lt;p&gt;➡️ &lt;a href="https://ko-fi.com/s/ab188420b7" rel="noopener noreferrer"&gt;Download Templates&lt;/a&gt;&lt;/p&gt;

</description>
      <category>godotengine</category>
      <category>prototyping</category>
      <category>testing</category>
      <category>resources</category>
    </item>
    <item>
      <title>Try Hack Me: Friday Overtime Complete Write-up 👾</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Fri, 26 Jul 2024 11:15:15 +0000</pubDate>
      <link>https://forem.com/christinec_dev/try-hack-me-friday-overtime-complete-write-up-4o46</link>
      <guid>https://forem.com/christinec_dev/try-hack-me-friday-overtime-complete-write-up-4o46</guid>
      <description>&lt;p&gt;In my most recent side-quest in life, I decided to dive back into the world of &lt;a href="https://www.kaspersky.co.za/blog/mission-hacking-grandma/10373/" rel="noopener noreferrer"&gt;&lt;em&gt;hAcK1_nG&lt;/em&gt;&lt;/a&gt;. The last time I was dabbling in the art of Cybersecurity, I focused more on red-teaming, but this time my interest is peaked by the life of a blue-teamer.&lt;/p&gt;

&lt;p&gt;That’s right, I’m joining The Defenders (trademark coming soon). But before I do that, let’s have a look at completing the &lt;a href="https://tryhackme.com/r/room/fridayovertime" rel="noopener noreferrer"&gt;&lt;em&gt;Friday Overtime&lt;/em&gt;&lt;/a&gt; room.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5au5x8gzz0hs5a9ctcuq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5au5x8gzz0hs5a9ctcuq.gif" alt="GIF" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So in this scenario, we are the only remaining CTI Analyst working overtime at PandaProbe Intelligence. We need to investigate potential file attachment breaches that are suspected to contain malware samples.&lt;/p&gt;

&lt;p&gt;Let’s start by running our machine. This might take a few minutes, so wait until your machine IP is populated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzytxi2kvwp69oi4u0tk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzytxi2kvwp69oi4u0tk.png" alt="Friday Overtime" width="645" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After your machine is up and running, let’s start answering our questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Who shared the malware samples?
&lt;/h3&gt;

&lt;p&gt;On the machine, open up Chromium and navigate to your given IP Address. At the top of the CentOS screen is an option to “Log in — DocIntel”. Click on it and log in with the given credentials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft13mrd6czzsndoqf0yvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft13mrd6czzsndoqf0yvp.png" alt="Friday Overtime" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F792k20byvub37sjll8i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F792k20byvub37sjll8i8.png" alt="Friday Overtime" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From there on you will be greeted by your email, which contains the information on the breach as well as the document containing the files, and the password to the document.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogerws8fgyiq7wgga3xk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogerws8fgyiq7wgga3xk.png" alt="Friday Overtime" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you scroll down, you will see the name of the person who shared the malware sample files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41wxw0muy52eel4xovpx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41wxw0muy52eel4xovpx.png" alt="Friday Overtime" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoobxmv39ffmdwq62btj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoobxmv39ffmdwq62btj.png" alt="Friday Overtime" width="800" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. What is the SHA1 hash of the file “pRsm.dll” inside samples.zip?
&lt;/h3&gt;

&lt;p&gt;To find this out, we will need to first download the actual attachment and extract the files from it. Click on the attachment on the right to download the file called “sample.zip”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fph6r901gm6cnbtfvtogi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fph6r901gm6cnbtfvtogi.png" alt="Friday Overtime" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnoq1cfth5nzmwn78hrj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnoq1cfth5nzmwn78hrj.png" alt="Friday Overtime" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwgx36daj0hfir0x0862.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwgx36daj0hfir0x0862.png" alt="Friday Overtime" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can either extract this zipped folder in the Command Line, or just by right-clicking it and extracting it manually. Remember, the password to this file is &lt;em&gt;Panda321!&lt;/em&gt;, so enter that when prompted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7pbkkg86g5et6ol9nlm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7pbkkg86g5et6ol9nlm.png" alt="Friday Overtime" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qenz4bo6sxfn87bqe06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qenz4bo6sxfn87bqe06.png" alt="Friday Overtime" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F492tgcb9lyxnaugtfn50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F492tgcb9lyxnaugtfn50.png" alt="Friday Overtime" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkf8myihyx7mda8h2wdr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkf8myihyx7mda8h2wdr9.png" alt="Friday Overtime" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9wie3o49ghiwc7wy5ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9wie3o49ghiwc7wy5ay.png" alt="Friday Overtime" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s open up our Terminal so that we can read the SHA1 hash of the file “pRsm.dll”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75yfcmf3ke3g3vut2g2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75yfcmf3ke3g3vut2g2p.png" alt="Friday Overtime" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To read the hash of our file, we will make use of &lt;a href="https://man7.org/linux/man-pages/man1/sha1sum.1.html" rel="noopener noreferrer"&gt;sha1sum&lt;/a&gt;. SHA1sum is a utility that computes and verifies SHA-1 cryptographic hash values. The primary reason you can use SHA1sum to read the hash of our .dll file — or any file, for that matter — is due to its ability to process binary data and generate a fixed-size hash value, which is a representation of the file’s content. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hqbqp1rwoaluviudeqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hqbqp1rwoaluviudeqy.png" alt="Friday Overtime" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcym0wj0s0ttdqdvacf1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcym0wj0s0ttdqdvacf1.png" alt="Friday Overtime" width="800" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Which malware framework utilizes these DLLs as add-on modules?
&lt;/h3&gt;

&lt;p&gt;For this question, I turned to good old Google to see if I could find any information on “pRsm.dll” and the framework used.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4ug39c304e49upl1e5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4ug39c304e49upl1e5x.png" alt="Friday Overtime" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I saw it flagged in &lt;a href="https://www.welivesecurity.com/2023/04/26/evasive-panda-apt-group-malware-updates-popular-chinese-software/" rel="noopener noreferrer"&gt;this&lt;/a&gt; article, so I clicked on it and searched for “framework”. Without too much effort, you can find the answer in the second paragraph of the article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7aem0f3vngm20urhhmxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7aem0f3vngm20urhhmxl.png" alt="Friday Overtime" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89sevlag1rc0lcssft78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89sevlag1rc0lcssft78.png" alt="Friday Overtime" width="800" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Which MITRE ATT&amp;amp;CK Technique is linked to using pRsm.dll in this malware framework?
&lt;/h3&gt;

&lt;p&gt;For this, we need to search “pRsm.dll” and look out for a Technique ID (TXXXX), since we see that the answer required has 5 characters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0f4epmvkw1f0su5k48z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0f4epmvkw1f0su5k48z.png" alt="Friday Overtime" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3ynp0povsuvgi2mpztw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3ynp0povsuvgi2mpztw.png" alt="Friday Overtime" width="800" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. What is the CyberChef defanged URL of the malicious download location first seen on 2020–11–02?
&lt;/h3&gt;

&lt;p&gt;Now we need to find a URL connected to 2020–11–02, and &lt;a href="https://medium.com/@hammazahmed40/understanding-defanging-of-ip-addresses-cf3efc190403" rel="noopener noreferrer"&gt;defang&lt;/a&gt; it on &lt;a href="https://gchq.github.io/CyberChef/" rel="noopener noreferrer"&gt;CyberChef&lt;/a&gt;. Defanging URLs and IPs is a critical practice for safely sharing potentially harmful links, and CyberChef simplifies this process, especially when handling large volumes of data. This practice is essential when sharing resources that might contain harmful data.&lt;/p&gt;

&lt;p&gt;Let’s head back to our article, and search for our date “2020–11–02”. We can see that it lands on a result that has a URL attached to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93wfihsde4ndsj0cuomg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93wfihsde4ndsj0cuomg.png" alt="Friday Overtime" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy and paste this URL into the CyberChef input, and add the recipe “Defang URL”. The output will give you your answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4z1xv0t5ilxtc6zmw3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4z1xv0t5ilxtc6zmw3s.png" alt="Friday Overtime" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuae042go2bsc3781m5cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuae042go2bsc3781m5cd.png" alt="Friday Overtime" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. What is the CyberChef defanged IP address of the C&amp;amp;C server first detected on 2020–09–14 using these modules?
&lt;/h3&gt;

&lt;p&gt;For this, we also need to search our date on the article we sourced previously. The IP should correlate to the date first seen on “2020–09–14”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0acghsr2cbpbemlwo5cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0acghsr2cbpbemlwo5cw.png" alt="Friday Overtime" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s copy this IP into the CyberChef input (remove the brackets because it should be pure data). Change the recipe to “Defang IP”. The result should be your answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72lk4xxo11p09wqa7znp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F72lk4xxo11p09wqa7znp.png" alt="Friday Overtime" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnapn3wtnlboda32sff9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnapn3wtnlboda32sff9.png" alt="Friday Overtime" width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. What is the SHA1 hash of the spyagent family spyware hosted on the same IP targeting Android devices on November 16, 2022?
&lt;/h3&gt;

&lt;p&gt;Unfortunately, we cannot find the SHA1 hash of the malware on the article that we’ve been using. But, luckily for us, we can make use of a service that analyzes files and URLs for viruses, worms, trojans, and other kinds of malicious content detected by antivirus engines and website scanners. &lt;/p&gt;

&lt;p&gt;Can you think of a service that can do all of the above? Well, we can use &lt;a href="http://hat%20analyzes%20files%20and%20URLs%20for%20viruses,%20worms,%20trojans,%20and%20other%20kinds%20of%20malicious%20content%20detected%20by%20antivirus%20engines%20and%20website%20scanners.%20It%20is%20particularly%20useful%20in%20the%20cybersecurity%20field%20for%20researching%20the%20characteristics%20of%20malware%20and%20the%20infrastructure%20used%20by%20cyber%20threats." rel="noopener noreferrer"&gt;VirusTotal&lt;/a&gt;. VirusTotal will allow us to search for the malware connected to the IP address, and analyze all of its characteristics. So let’s open up the site and search for any data connected to our “fanged” IP address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnde4xgbhzcxkc36ec9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnde4xgbhzcxkc36ec9j.png" alt="Friday Overtime" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the “Relations” panel to see where this IP has been flagged. This panel helps us explore the relationships between various indicators of compromise (IoCs) such as files, URLs, domains, and IP addresses.&lt;/p&gt;

&lt;p&gt;You will see that an IoC from this IP was picked up on Android on the date of 2022–11–16. This is the name of our spyagent family spyware.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjy1kffosxxsgjy8lcp0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjy1kffosxxsgjy8lcp0e.png" alt="Friday Overtime" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now all we need is the hash value of this spyagent. Copy the name and search it. If we click on the “Details” of our result, we will see that there is a SHA1 hash value, which is what we need for our final flag!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsc9880rmyhezgmt9ebx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsc9880rmyhezgmt9ebx.png" alt="Friday Overtime" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpnusbn798hpxesyka81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpnusbn798hpxesyka81.png" alt="Friday Overtime" width="800" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Congratulations on completing the room. I hope you found the writeup valuable, and that you could follow along with ease.&lt;/p&gt;

&lt;p&gt;Now, onwards to the next room! 😊&lt;/p&gt;




</description>
      <category>tryhackme</category>
      <category>writeup</category>
      <category>tutorial</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>I Made a Simple 2D Pathfinding &amp; Navigation Tool for Unity!</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Sat, 06 Apr 2024 17:16:32 +0000</pubDate>
      <link>https://forem.com/christinec_dev/i-made-a-simple-2d-pathfinding-navigation-tool-for-unity-j9k</link>
      <guid>https://forem.com/christinec_dev/i-made-a-simple-2d-pathfinding-navigation-tool-for-unity-j9k</guid>
      <description>&lt;p&gt;Recently whilst I was busy working on a 2D game in Unity, I had to add the functionality to have an Enemy AI navigate up and down a predefined path. Rather than resorting to downloading a plugin or implementing a complex A* Pathfinding algorithm for a single enemy, I decided to create a simple tool that would allow me to draw my navigation path directly in the game scene! This path could then be assigned to an entity AI, enabling them to move randomly along the path without all of the complexities. I named this tool NavPath2D, and it’s available for free use. 😊&lt;/p&gt;

&lt;p&gt;This tool works as a GUI-based tool that allows you to draw paths (that entities such as your AI should follow) directly in your Unity Editor scene. &lt;/p&gt;

&lt;p&gt;These paths can then be saved as prefabs and assigned to entities. These entities will then randomly select a path to move on, eliminating the need for complex A* pathfinding algorithms. &lt;/p&gt;

&lt;p&gt;So, if you are someone who needs a simple pathfinding solution for your 2D game (especially since Unity does not support NavMeshes for 2D), then this tool can help you by offering a straightforward alternative to more complex solutions. You also have the flexibility to expand upon the basic functionality, making it adaptable to various genres and project requirements. &lt;/p&gt;

&lt;p&gt;You can find the download link and information on my &lt;a href="https://github.com/christinec-dev/NavPath2D" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*&lt;em&gt;Please note that this tool is meant for simple navigation, and it will not give you the uniqueness that you can achieve through the use of A&lt;/em&gt; Pathfinding algorithms. There are plenty of tools out there, many paid and expensive, so this tool was made to be an easy and affordable solution to 2D navigation issues.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Tool Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GUI-based Path Creation:&lt;/strong&gt; You can draw paths directly in the Unity Editor scene, providing a visual and intuitive way to define movement paths for 2D entities. This feature allows for the creation of paths that can navigate around obstacles, follow specific routes, and more, offering flexibility in how paths are formed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Path Selection:&lt;/strong&gt; Once paths are created, they can be saved as prefabs. This functionality facilitates easy reuse and assignment to different entities within the project. Additionally, entities can be assigned multiple paths, enabling them to randomly decide which path to follow, adding an element of unpredictability to their movement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Entity Movement Along Paths:&lt;/strong&gt; AI Entities can be assigned paths, enabling them to move along the defined waypoints. This feature eliminates the need for complex A* pathfinding algorithms, simplifying path management for 2D games and making it easier to implement straightforward movement patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Pathfinding for 2D:&lt;/strong&gt; This tool addresses the lack of a built-in NavMesh feature for 2D in Unity by offering a straightforward solution for pathfinding. It provides a simple yet effective way to manage entity movement in 2D environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customizable and Expandable:&lt;/strong&gt; The tool is designed to be a simple solution for basic pathfinding needs but also allows for expansion and customization to fit more complex scenarios. You can add your movement customizability by defining more randomization in movement, animations, and more.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3840%2F0%2A7WDxjQuKtk31X3ew" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3840%2F0%2A7WDxjQuKtk31X3ew" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3840%2F0%2AouxJVdfLd_dTQtRI" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3840%2F0%2AouxJVdfLd_dTQtRI" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3840%2F0%2AvJ4EHaMpwGAx05Is" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3840%2F0%2AvJ4EHaMpwGAx05Is" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Usage Instructions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Download and Import:
&lt;/h3&gt;

&lt;p&gt;Download the NavPath2D package and import it into your Unity project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A8j-WhK1ms5giXOOh" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A8j-WhK1ms5giXOOh" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup AI Entity:
&lt;/h3&gt;

&lt;p&gt;Ensure you have an AI entity set up in your Unity project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AI4mp5fB1EQAMf2ep" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AI4mp5fB1EQAMf2ep" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Path GameObject:
&lt;/h3&gt;

&lt;p&gt;In your game scene, add a new empty GameObject and rename it to something like “Path_01”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuJAj8ZoXbl1J0Jj6" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuJAj8ZoXbl1J0Jj6" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ACH3ArjEPPiCnIP-h" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ACH3ArjEPPiCnIP-h" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Path Script:
&lt;/h3&gt;

&lt;p&gt;Attach the &lt;strong&gt;Path.cs&lt;/strong&gt; script to this GameObject. This script (which can be found in the Scripts/NavPath2D folder) allows you to draw paths onto your scene via the PathEditor.cs (found in ssets/Editor/NavPath2D/) Editor script as it holds the Waypoints that we add.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADzAVEc7o45oi_Oq9" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADzAVEc7o45oi_Oq9" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AamzvGq7J_JfTXmmT" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AamzvGq7J_JfTXmmT" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Manage Waypoints:
&lt;/h3&gt;

&lt;p&gt;With the GameObject selected, you can start adding, removing, and moving waypoints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To add a waypoint, SHIFT-click in the scene window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To move a waypoint, click on the waypoint gizmo in the scene window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To remove a waypoint, CTRL-click on the waypoint gizmo in the scene window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To add a waypoint to an existing waypoint, select it and SHIFT-click a new waypoint.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Al4HbsG8NWUUsaKob" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Al4HbsG8NWUUsaKob" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKIezmqafTlF5yzeQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKIezmqafTlF5yzeQ" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AwLbNuYGfWwAIH49t" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AwLbNuYGfWwAIH49t" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4Osg_B23toqGGePE" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4Osg_B23toqGGePE" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can add multiple GameObjects with the Path.cs script added to it to create multiple paths.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save Path as Prefab:
&lt;/h3&gt;

&lt;p&gt;Once you’re done creating paths, drag the GameObject into your directory to turn it into a Prefab. This allows you to assign it to your entity. You can remove this prefab from the scene hierarchy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuWgDgOVO-VaBpqcy" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuWgDgOVO-VaBpqcy" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6DR4Y3Uvd8z0x1ai" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6DR4Y3Uvd8z0x1ai" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6XGCLPOb38z2uPEr" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6XGCLPOb38z2uPEr" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Assign Path to Entity:
&lt;/h3&gt;

&lt;p&gt;Select your entity and attach the &lt;strong&gt;Walker.cs&lt;/strong&gt; (which can be found in the Scripts/NavPath2D folder) script to it. This is a demo script which allows you to assign the path prefabs to your entity, enabling it to randomly move along the paths. You can expand this script to include logic for breaks within movement, animations, etc., or combine it with your existing scripts. In the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RandomWalker&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// path it chooses to walk on&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// waypoint index&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//entity speed - how fast it will move&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;waypointTolerance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//how close it stays to path - the lower this value, the more accurate it is (do not set to 0).&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pathPrefabs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//path options entity can select from &lt;/span&gt;

        &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Randomly choose and instantiate a path from the path prefabs addded&lt;/span&gt;
            &lt;span class="n"&gt;GameObject&lt;/span&gt; &lt;span class="n"&gt;pathGO&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathPrefabs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathPrefabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
            &lt;span class="n"&gt;currentPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pathGO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Move entity randomly on the waypoints of chosen path&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;waypointTolerance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="k"&gt;else&lt;/span&gt;
                  &lt;span class="p"&gt;{&lt;/span&gt;
                      &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nextWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;GetRandomConnectedWaypointIndex&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// found in Waypoint.cs&lt;/span&gt;
                      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                      &lt;span class="p"&gt;{&lt;/span&gt;
                          &lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextWaypointIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                      &lt;span class="p"&gt;}&lt;/span&gt;
                      &lt;span class="k"&gt;else&lt;/span&gt;
                      &lt;span class="p"&gt;{&lt;/span&gt;
                          &lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                      &lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;waypointPosition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waypoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;currentWaypointIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MoveTowards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;waypointPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltaTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A1qYD1yOLodE5rR5H" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A1qYD1yOLodE5rR5H" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Paths to Entity:
&lt;/h3&gt;

&lt;p&gt;Now add the path prefabs that you created to the waypoint list on the script attached to your Entity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsjFNGBna6u7CGjxR" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsjFNGBna6u7CGjxR" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Run Your Scene:
&lt;/h3&gt;

&lt;p&gt;Finally, run your scene. Your entity should now choose a path to move on and move between the waypoints. Remember, the lower the waypointTolerance variable value, the closer the entity will walk to the waypoint path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A9TBDjByuY_QhA6Rl" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A9TBDjByuY_QhA6Rl" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4qyJtRF5iF2gLBca" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4qyJtRF5iF2gLBca" alt="NavPath2D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tool not only streamlines the process of defining movement paths for AI entities but also eliminates the need for over-the-top pathfinding algorithms, making it an efficient solution for basic 2D games. NavPath2D addresses the absence of a built-in 2D pathfinding system in Unity, offering a straightforward alternative for managing entity movement in 2D environments! ❤️&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>tooling</category>
      <category>gamedev</category>
      <category>package</category>
    </item>
    <item>
      <title>I Made a Batch Sprite Animation and Library Creation Tool for Unity</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Sun, 17 Mar 2024 09:27:32 +0000</pubDate>
      <link>https://forem.com/christinec_dev/i-made-a-batch-sprite-animation-and-library-creation-tool-for-unity-1fo5</link>
      <guid>https://forem.com/christinec_dev/i-made-a-batch-sprite-animation-and-library-creation-tool-for-unity-1fo5</guid>
      <description>&lt;p&gt;Recently, I’ve been playing around in the Unity Engine. Usually, for my own personal projects, I’d usually turn to Unreal Engine or Godot — but once I started creating in Unity, I fell in love! The one thing that bothered me is how long it takes to create 2D animations — especially if you have a spritesheet with multiple animations, or character spritesheets who follow the same layout.&lt;/p&gt;

&lt;p&gt;Because of this, I decided to make my own tool to help solve my own problem. &lt;a href="https://github.com/christinec-dev/SpriterNator" rel="noopener noreferrer"&gt;SpriterNator&lt;/a&gt; is a Unity extension that simplifies the process of generating and managing 2D sprite animations and sprite libraries. This tool makes it easier to create, organize, and export sprite-based assets within the Unity ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3832%2F1%2ArwEUG7HtQlyc4FQT36E4ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3832%2F1%2ArwEUG7HtQlyc4FQT36E4ng.png" alt="Preview of SpriterNator — where you can create animations and sprite libraries" width="800" height="420"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Preview of SpriterNator — where you can create animations and sprite libraries&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With this tool, you can batch create and manage Animation assets and Sprite Library assets — which will help reduce development time, allowing you to focus on the creative aspects of game development! 😊&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can find the package and the repository that I created for it below:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/christinec-dev/SpriterNator" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oops-i-devd.gitbook.io/christinec-dev" rel="noopener noreferrer"&gt;GitBook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.gg/4N6b4bkC8h" rel="noopener noreferrer"&gt;Join My Discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ko-fi.com/christinedevs" rel="noopener noreferrer"&gt;Support Me&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  FEATURES
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Batch Animation Creation
&lt;/h3&gt;

&lt;p&gt;Automatically generate multiple animations from a single spritesheet, reducing manual setup time. Define animations using start and end frames, and export them as Unity Animation Clips (.anim).&lt;/p&gt;

&lt;h3&gt;
  
  
  Sprite Sheet Swapping
&lt;/h3&gt;

&lt;p&gt;Effortlessly switch between spritesheets that follow the same layout. This feature is for developers working with characters or objects that have multiple skins or states, enabling quick swaps without needing to adjust frame ranges or manually creating or dragging animations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Animation List Management
&lt;/h3&gt;

&lt;p&gt;Add, remove, and duplicate animations directly from the tool’s UI. Organize your animation sequences efficiently, with support for reordering through intuitive controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save and Load Presets
&lt;/h3&gt;

&lt;p&gt;Save your animation settings as JSON files for future use. This functionality allows for easy reapplication of animation sequences to new spritesheets, significantly speeding up the development process when working with multiple characters or assets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sprite Library Asset Creation
&lt;/h3&gt;

&lt;p&gt;Streamline the organization of sprites into categories and labels by creating Sprite Library assets directly from your animations. This feature organizes sprites based on animation names and frames, facilitating quick access and reuse within your projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  USAGE OVERVIEW
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. SpriteSheet Preparation
&lt;/h3&gt;

&lt;p&gt;This tool works with spritesheets, so whether you are using it for one simple spritesheet, multiple spritesheets, or a large collection of spritesheets that follow the same layout or pattern (such as for a character creator system), make sure that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You split your sprite sheets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When splitting the sheets, ensure that each frame is cropped out correctly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2184%2F1%2AETG02QUcsHCGtIWkn486hA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2184%2F1%2AETG02QUcsHCGtIWkn486hA.png" alt="SpriterNator" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AxCOHNaTrGlpafBBIpAShBQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AxCOHNaTrGlpafBBIpAShBQ.png" alt="Example of my character spritesheets, which contains two seperate character sheets that are split. You can see they follow the same format and layout." width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Example of my character spritesheets, which contains two seperate character sheets that are split. You can see they follow the same format and layout.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Download the Package
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/christinec-dev/SpriterNator/tree/main/Package" rel="noopener noreferrer"&gt;Download&lt;/a&gt; the package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With your project open, double click the package file to add it to your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once added to your project, you should be able to see it in your project via Tools/SpriterNator.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A24kHEQT6tt7ftP8yq_vU8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A24kHEQT6tt7ftP8yq_vU8A.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Adding Animation Properties
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select the spritesheet (not the individual frame, the complete spritesheet) asset that you want to use to create animations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also set the location to where your assets should save.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you plan on creating a Sprite Library asset from your animations, add a name for this asset.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2ArdJeIUBLt1h5JBMT4oJN6Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2ArdJeIUBLt1h5JBMT4oJN6Q.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A5qi8MVzErULUcyBdO7hpyQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A5qi8MVzErULUcyBdO7hpyQ.png" alt="f" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Create Your Animations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You can &lt;strong&gt;add&lt;/strong&gt; animations to the list via the “+” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can &lt;strong&gt;remove&lt;/strong&gt; animations from the list via the “-” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can &lt;strong&gt;duplicate&lt;/strong&gt; list animations via the “++” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When creating an animation, enter the first frame, last frame, and frame rate of your animation. Also state whether or not it should loop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can find the first frame value on your spritesheet at the end of the frame naming “_x”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can find the last frame value on your spritesheet at the end of the frame naming “_x”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The frame rate is added automatically, but you can change it if you want.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AAYYhaxSe_k9qEKGZm2ZfMw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AAYYhaxSe_k9qEKGZm2ZfMw.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2ASuq4MexPOZJnTV8tzlHl4Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2ASuq4MexPOZJnTV8tzlHl4Q.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2Afnme-ZPPrGbOir0gAIvODA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2Afnme-ZPPrGbOir0gAIvODA.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AG-TyrLfmvx8sfDtw-9AVNw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AG-TyrLfmvx8sfDtw-9AVNw.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2Af4M_HD67RGTk9XqhjPokDg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2Af4M_HD67RGTk9XqhjPokDg.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2Ani9fmAx1hRei_82mX2iRfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2Ani9fmAx1hRei_82mX2iRfg.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AKn5garV9zfP0HGHT-LtHBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AKn5garV9zfP0HGHT-LtHBA.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Export Your Animations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you’ve created your animations, and you want to export them as .anim assets, click the “CREATE ANIMATIONS” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can go to the directory where you saved it, and the animations should be there. The tool automatically focuses on this folder for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, you can add your character to your preview panel, and test the animation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A7JHsEkkqTVi5rLyI9diuYg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A7JHsEkkqTVi5rLyI9diuYg.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AgW02jTED7WPSReQserKFCw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AgW02jTED7WPSReQserKFCw.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Create Your Sprite Libraries
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you’ve created your animations, and you want to export them as .asset assets, click the “CREATE SPRITE LIBRARY” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your animation names will be assigned as &lt;strong&gt;Categories&lt;/strong&gt;, and your animation frames per animation will be assigned as **Labels **to these Categories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’ll have to convert the runtime asset that it created into a library asset. Select the asset, and in the Inspector Panel, click on “Open Sprite Library Asset Upgrader”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load your created library asset, and upgrade it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your Sprite Library should now be created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AEDCk6ikAsdRp6kyK1aDIsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AEDCk6ikAsdRp6kyK1aDIsg.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AJ062NYLgyeMBs5LQjgnoKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AJ062NYLgyeMBs5LQjgnoKA.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A2185UlCq34VVWZCMHkaA7A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2A2185UlCq34VVWZCMHkaA7A.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Export &amp;amp; Import Your Animation Lists
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you have similar spritesheets, and you’d like to come back later to create animations for another character using the same animation frames and naming conventions, then you can save your animations as a JSON file via the “SAVE LIST” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can edit this file to add more animations, and then load it again using the “LOAD LIST” button.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AgaDbojttZX4vSmbLyXoh0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AgaDbojttZX4vSmbLyXoh0g.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Reuse Your Created Animations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you have similar spritesheets, and you want to create the same animations for Character_2 as you did for Character_1, then you can simply just drag in your new spritesheet into the properties panel, and change your naming and/or save location of the asset.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simply click “CREATE ANIMATIONS”, and your new character will have the same animations!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This assumes that they have the same spritesheet and animation layout.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AOIUmNWY2dHxV2x9j5_lJsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AOIUmNWY2dHxV2x9j5_lJsw.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AohDmt2vfU3dFFoADCKXJUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F7040%2F1%2AohDmt2vfU3dFFoADCKXJUw.png" alt="SpriterNator" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;And there you have it! I hope this tool saves you some time when creating 2D animations and Sprite Libraries in Unity —  because I know that it’s saving me time. I might add to it later on, and if so, I will update this post. Until then, happy developing! 😊&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>gamedev</category>
      <category>automation</category>
      <category>animation</category>
    </item>
    <item>
      <title>Let’s Learn Godot 3D by making an Endless Runner Game — Part 3: Player Setup &amp; Animations👟</title>
      <dc:creator>christine</dc:creator>
      <pubDate>Sat, 09 Mar 2024 20:49:32 +0000</pubDate>
      <link>https://forem.com/christinec_dev/lets-learn-godot-3d-by-making-an-endless-runner-game-part-3-player-setup-animations-7di</link>
      <guid>https://forem.com/christinec_dev/lets-learn-godot-3d-by-making-an-endless-runner-game-part-3-player-setup-animations-7di</guid>
      <description>&lt;p&gt;With our environment created, we can go ahead and start with creating our player, who will move forward when we start the game, and we’ll be able to move them left, right, and up. If you look in your Assets directory, you’ll see that I already downloaded our player mesh and all of their animations. But let’s say you want to use your own character with different animations. Don’t worry, I’m going to show you how to do that!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F1%2AkWglbkX_o1Rk5w5aqdDtTg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F1%2AkWglbkX_o1Rk5w5aqdDtTg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 15: Our player. The FBX scene contains our rigged player skeleton and mesh, and the .png files contain the materials for our mesh.&lt;/p&gt;

&lt;p&gt;Okay, so let’s first see where we can find a 3D character. Please don’t drag any of the animations and 3D characters into your current project — create a separate “test” project for this as this part will just show you how to get your own characters and animations. I thought this would be valuable for you since you’re probably learning 3D development to make your own games.&lt;/p&gt;

&lt;p&gt;You can find 3D characters on most asset stores — but the one that might be the best for Godot is &lt;a href="https://itch.io/game-assets/free/tag-3d/tag-characters" rel="noopener noreferrer"&gt;itch.io&lt;/a&gt;. Just make sure that the character that you download is rigged — or that you know how to rig a character in software such as Blender. A rigged character has been given an internal, movable skeleton, known as a rig. This rig is used to animate the character in a 3D environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3100%2F1%2AxYmacol1FRA6MAQdK5vECA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3100%2F1%2AxYmacol1FRA6MAQdK5vECA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another place to find base characters for a demo game (like ours) is &lt;a href="https://www.mixamo.com/#/" rel="noopener noreferrer"&gt;Mixamo&lt;/a&gt;, which is the place where we also find our animations. You’ll see that this is where I found AJ, our runner character!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3830%2F1%2AxK13x-xEgLl0UhB1dASSoA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3830%2F1%2AxK13x-xEgLl0UhB1dASSoA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s download a simple and free rigged character on Itch.io, then upload it to Mixamo so that we can animate them. Download this &lt;a href="https://vinrax.itch.io/psx-secretary-character" rel="noopener noreferrer"&gt;PSX-styled secretary&lt;/a&gt; by Vinrax.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2382%2F1%2AltAoKX2zRMJUZ_gamR-2PA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2382%2F1%2AltAoKX2zRMJUZ_gamR-2PA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unzip the downloaded folder, and you’ll see inside the folder is the fbx for the character. Remember, this FBX contains the character’s mesh, collision, rig, and materials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AZ4Q8oxfBTyIUKJiQa9NpRA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AZ4Q8oxfBTyIUKJiQa9NpRA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s head back to Mixamo and select the option to “Upload Character”. You want to upload your secretary character’s .fbx here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AHSk2Yg9R6EfqVqtMdHmHug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AHSk2Yg9R6EfqVqtMdHmHug.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2354%2F1%2AeIwfgvb0dVFelFhCSnG3eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2354%2F1%2AeIwfgvb0dVFelFhCSnG3eg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2352%2F1%2A45285BCuZqOorYNzo4jZ5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2352%2F1%2A45285BCuZqOorYNzo4jZ5g.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now search for and play any animation, and the animation should play on your uploaded character.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3820%2F1%2AAGwfBk-mtoR5qlrR0yYSiQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3820%2F1%2AAGwfBk-mtoR5qlrR0yYSiQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you’re happy with your animation, you can press download. We want to download the player with the skin because this will apply the animation directly to our character, which we need for Godot!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ah8yNuxspfN1TxeoxQ_G-4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ah8yNuxspfN1TxeoxQ_G-4w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then you can just drag it into your project.&lt;/p&gt;

&lt;p&gt;Now, since this was a demo to show you how to download and animate characters, we’re not going to continue with our secretary character. No, instead we’ll go back to our project and set up our player with the animations for our AJ character. You’ll see in your assets directory we have a base fbx, which is our player’s base skeleton (so, think of your initial downloaded secretary), and then we have fbx files for our animations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AiADTRA3RSXPAzft1LjfQdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AiADTRA3RSXPAzft1LjfQdA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 16: Our base character&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2At4guwLGKI8TSg-Wnv2x9JQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2At4guwLGKI8TSg-Wnv2x9JQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 17: Our animations.&lt;/p&gt;

&lt;h2&gt;
  
  
  PLAYER SETUP
&lt;/h2&gt;

&lt;p&gt;Let’s create a new scene with a &lt;a href="https://docs.godotengine.org/en/stable/classes/class_characterbody3d.html" rel="noopener noreferrer"&gt;CharacterBody3D&lt;/a&gt; node as its root node. A CharacterBody3D is a type of node that is used for characters that need to be controlled via code, especially in cases where physics simulation is required for movement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A1mXk4l7Vgdx4QdoOSQSZAw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A1mXk4l7Vgdx4QdoOSQSZAw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rename this root node to Player and save the scene underneath your “Scenes” folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AJ4QqbvYhlABwb7yRw5osRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AJ4QqbvYhlABwb7yRw5osRQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see that next to the newly added node there is a yellow warning symbol. If you click on it, it tells us that our node needs a collision shape — because it’s a physics body, and for it to interact with other bodies in our game, it needs a collision.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AUkco3HwCGnC2HGam2qDTUg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AUkco3HwCGnC2HGam2qDTUg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s add a CollisionShape3D node to fix this. In the Inspector Panel, we’ll assign a simple &lt;a href="https://docs.godotengine.org/en/stable/classes/class_collisionshape3d.html" rel="noopener noreferrer"&gt;CapsuleShape3D&lt;/a&gt; to our collision, which will encapsulate our entire player.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AUkM4LNP6y7Zko59x_iUX3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AUkM4LNP6y7Zko59x_iUX3w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbumuZC0M7e6i-HDdAmLqpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbumuZC0M7e6i-HDdAmLqpw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on your character, you can make this shape bigger or smaller via its radius and height properties.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ap8e0SD2Hy-2-iDjB4irIyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ap8e0SD2Hy-2-iDjB4irIyA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s drag our AJ.fbx (our base character) into this scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2054%2F1%2AvdxsNsxnDWxinajOIw12FA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2054%2F1%2AvdxsNsxnDWxinajOIw12FA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want to open up this FBX scene so that we can see our players skeleton, and get to our &lt;a href="https://docs.godotengine.org/en/stable/classes/class_animationplayer.html" rel="noopener noreferrer"&gt;AnimationPlayer&lt;/a&gt; node, which the fbx adds all of our player’s animations to. To do this, we should right-click on our “Root Node” and select the option to make it local. “Make Local” will make the scene local to our current scene, so that we can treat the nodes as individual components instead of instanced scene components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A-EaD7dmCu5Vqwq0hN5f9vw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A-EaD7dmCu5Vqwq0hN5f9vw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgmtGUDg8hAmUV3HsezX5iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgmtGUDg8hAmUV3HsezX5iw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From this localized scene, delete the node named “Bottom”. It has no functionality, so delete it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AO1vI-Ryg3goUbUJLUScU6Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AO1vI-Ryg3goUbUJLUScU6Q.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the “Root Scene” node and move it down into the collision shape.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2498%2F1%2AVSXegwFZw_ct3YupRnvsIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2498%2F1%2AVSXegwFZw_ct3YupRnvsIQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ADv50SMgnZwALckIgMBow6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ADv50SMgnZwALckIgMBow6w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see that your &lt;a href="https://docs.godotengine.org/en/stable/classes/class_skeleton3d.html" rel="noopener noreferrer"&gt;Skeleton3D&lt;/a&gt; node contains your rig with all of your bones, and all the &lt;a href="https://docs.godotengine.org/en/stable/classes/class_meshinstance3d.html" rel="noopener noreferrer"&gt;MeshInstance3D&lt;/a&gt; nodes within it contains the “skin” that form over these bones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AztZqZJ79dvrXggTPvJPS9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AztZqZJ79dvrXggTPvJPS9w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2An9kRcHsAubSO6xytQbQHXw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2An9kRcHsAubSO6xytQbQHXw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AuKpOe97c59a6g0Pv6v21lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AuKpOe97c59a6g0Pv6v21lg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 18: Our rigged skeleton.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Aas5WWqv89-en2t-2zCpunw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Aas5WWqv89-en2t-2zCpunw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 19: Our player’s skin.&lt;/p&gt;

&lt;p&gt;The “skin” has a 3D mesh, is assigned to the skeleton, and it also has an assigned material.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ai12mrPuHhGMyzTj15f6MvQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ai12mrPuHhGMyzTj15f6MvQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll notice that his mouth and eyes are missing, and this is because the mesh instances have no material assigned to them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AomESxCGCrKoKrzXDdg5cBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AomESxCGCrKoKrzXDdg5cBA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select your “h_Geo” node (which is our mouth), and in its Surface Material Override property, drag in your “Boy01_FacialAnimMap.png” material, which can be found underneath the Player &amp;gt; AJ.fbm directory. This material contains the mesh for our player’s facial features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AKwNrz1bI9kldOKBl4T7D4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AKwNrz1bI9kldOKBl4T7D4g.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AnKgGtQuYPPLLErbnwyTH-A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AnKgGtQuYPPLLErbnwyTH-A.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AEOoN87idqX0BXOnN9ln22w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AEOoN87idqX0BXOnN9ln22w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get rid of the white overlay, select the material property that you just added and navigate to Transparency &amp;gt; Transparency, and change the mode to “Alpha”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7Hb3YmC_XgbeuMqZ4K9ZXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7Hb3YmC_XgbeuMqZ4K9ZXQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A0VaukbggBTWlSUKC_TNcVg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A0VaukbggBTWlSUKC_TNcVg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s follow the same steps for our “Boy01_Eyes_Geo” and “Boy01_Brows_Geo” nodes. Your final face “skins” should look like the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgOpJow1VkSg6vH9sCpuuog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgOpJow1VkSg6vH9sCpuuog.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our player is also a bit too shiny, and this is because of their specular value on the default material that the engine added to the “Boy01_Body_Geo” node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2406%2F1%2A9gSw3aEnblnsnR_7pHGBhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2406%2F1%2A9gSw3aEnblnsnR_7pHGBhw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Material layers in game development are used to create realistic and visually appealing textures on 3D models. Each layer serves a specific purpose in simulating how light interacts with the surface of objects. Here’s an overview of some common material layers used in games:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Albedo (or Diffuse):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The albedo texture doesn’t contain any lighting information; it only stores the colors as they are.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Normal Map:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This creates the illusion of depth and detail by affecting the way light bounces off the surface, which can make a flat surface appear textured.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Roughness (or Glossiness):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The roughness layer controls how shiny or matte the surface appears. A low roughness value indicates a smooth surface that reflects light sharply, like a mirror, while a high roughness value will scatter light, giving a more diffuse reflection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Metallic:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This layer determines how metallic a surface is. Non-metallic materials (like wood or plastic) have low metallic values, while metals have high metallic values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Specular:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specular maps define the reflectivity of a surface at direct angles of light. They can be used to create varying levels of shine across different parts of a material.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ambient Occlusion:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s a way to add soft shadows in areas where light has a harder time reaching, enhancing the realism of nooks and crannies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Emission (or Emissive):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emission textures make parts of a material emit light of their own. This can simulate effects like glowing screens, bioluminescent creatures, or hot metal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Opacity (or Transparency):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opacity maps define the transparency of different areas of a material. They can be used to create effects like glass, water, or semi-transparent fabrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get rid of the specular value, we need to drag our diffuse/albedo material into our “Boy01_Body_Geo” nodes Surface Material Override property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ALa5YPRyReOaoRd-VB9RMmQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ALa5YPRyReOaoRd-VB9RMmQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A-45C6XKSlSWQ76uNAUX1Wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A-45C6XKSlSWQ76uNAUX1Wg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also play around with the material layer values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ANW3pp0RLo254PIlxTAvC4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ANW3pp0RLo254PIlxTAvC4w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your player should now be shine free and have a face!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A6b_yDAJS43-GMkOYj6SupA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A6b_yDAJS43-GMkOYj6SupA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ANIMATIONS SETUP
&lt;/h2&gt;

&lt;p&gt;If you select your &lt;a href="https://docs.godotengine.org/en/stable/classes/class_animationplayer.html" rel="noopener noreferrer"&gt;AnimationPlayer&lt;/a&gt; node, you will see that each bone of our Skeleton3D node has been animated for each frame within our animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AdPDZ8AQtlSqc8Wg0LoViQQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AdPDZ8AQtlSqc8Wg0LoViQQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add an animation from our downloaded FBX animations, we’ll need to drag each fbx scenes into our folder and get the animations from their trees. We’ll save these animations, and then add them to our pre-existing AnimationPlayer node. Okay, let’s break this down into steps. Let’s start with our “Idle.fbx”, which contains our idle animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ANSVnEIAvus_cfZ6OkDcqBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ANSVnEIAvus_cfZ6OkDcqBA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Drag this fbx into your scene tree and make it local to your scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AX9bBwxxtqSur-Gbpl9Yp8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AX9bBwxxtqSur-Gbpl9Yp8w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7nV6D89zqAMg_J2L3G46rA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7nV6D89zqAMg_J2L3G46rA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save your scene. Select the AnimationPlayer node from this scene, and in the panel below, select the option to “Manage Animations”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AGTkbXsBb-y63GIz_4vtKaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AGTkbXsBb-y63GIz_4vtKaw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Double click the “mixamo” animation, and rename it to “Idle”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AEZ33gNznbeamoo5irT7VWQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AEZ33gNznbeamoo5irT7VWQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Am00nP0p2S4PGFp56L23c3Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Am00nP0p2S4PGFp56L23c3Q.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the save icon next to your Idle animation, and let’s save it underneath a new folder called “Resources”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7cqyYVYMNAmcBPU7QOOS0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A7cqyYVYMNAmcBPU7QOOS0w.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A41_IBDLImk7md7t7wjCAIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A41_IBDLImk7md7t7wjCAIQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have our animation saved, and our animation can be added to any other body that has the exact same skeleton as our Idle.fbx scene — so, in other words, it can be added to any other AnimationPlayer node that is assigned to our AJ character.&lt;/p&gt;

&lt;p&gt;Delete the localized scene — we don’t need it anymore since we’ve gotten the animation that we needed from it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AwQrs6GtCNaW9rmL6n4MFKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AwQrs6GtCNaW9rmL6n4MFKA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A1fizUpWvNZ7UwL9zXoOMdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A1fizUpWvNZ7UwL9zXoOMdw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to add the animation from our Resources folder to our initial AnimationPlayer, so head into the “Manage Animations” panel in your AnimationPlayer node. You can delete the two default animations within it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbvLXgPc54yqcigWx0uHvZQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbvLXgPc54yqcigWx0uHvZQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the folder icon next to the AnimationLibrary and load the saved Idle animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbJ7XwcCkK-e4zq6Z-nMZjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbJ7XwcCkK-e4zq6Z-nMZjg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ALRq4xvwPWEwFrPjvYytvKA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ALRq4xvwPWEwFrPjvYytvKA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see that the animation is automatically added to our Skeleton3D node. Enable the “looping” option so that our idle animation can loop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2934%2F1%2AiwL83xe8VSHKtYu-92WAIA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2934%2F1%2AiwL83xe8VSHKtYu-92WAIA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A5IaBwDa4dHDBeuRQqqIKvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A5IaBwDa4dHDBeuRQqqIKvg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you play the animation, it should loop and it should play.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2934%2F1%2AexSKwhP25SoaDEeHbpYTkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2934%2F1%2AexSKwhP25SoaDEeHbpYTkw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s follow the same step for our Running (save as Running) and RunningJump (save as Jump) animations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ayxw8LfvguQAXgmBMHx18Jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ayxw8LfvguQAXgmBMHx18Jg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ADOg8F2eUAHgPrjSAa2yyRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ADOg8F2eUAHgPrjSAa2yyRw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8hevphEGuATLiFLQHlpncQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8hevphEGuATLiFLQHlpncQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgPZM04xzLIhdCu7_TopoWw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgPZM04xzLIhdCu7_TopoWw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AfzH4o_l9POuodEjascio-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AfzH4o_l9POuodEjascio-Q.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ATmEYlxnRIwvtLc2fCH7bmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ATmEYlxnRIwvtLc2fCH7bmg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want to enable looping for our Running animation as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2356%2F1%2AfB3RFREWCW7JZ6rh1lpITw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2356%2F1%2AfB3RFREWCW7JZ6rh1lpITw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then we also want to prevent our player from moving forward when they jump. All our animations should play in place. So, to do this, we need to disable our player’s hips when they jump, since this moves them forward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2320%2F1%2A9x2cKIcx2GgCGpZaXm2pnA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2320%2F1%2A9x2cKIcx2GgCGpZaXm2pnA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is our animations set up for our game!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3352%2F1%2AZY-zNbUqL4c0GdGj9jmVPA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3352%2F1%2AZY-zNbUqL4c0GdGj9jmVPA.png" alt="Godot 3D Endless Runner" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ANIMATION STATE MACHINE
&lt;/h2&gt;

&lt;p&gt;Now all we need to do is to add these animations to an Animation State Machine. This state machine allows for a smooth animation flow, ensuring that the character’s visual state always matches their gameplay state. The system looks for conditions or triggers set in the code or through player interaction to move from one animation to another, creating a dynamic and immersive experience.&lt;/p&gt;

&lt;p&gt;Our state machine will play the idle animation when the level is loaded. When we start the game, our machine will switch over to the running animation, and when we jump, we will switch from the running animation to the jumping animation. After the jump is complete, we will switch back to the running animation, and if the game ends, we will switch back to the idle animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2534%2F1%2ALdN5sPdgDL0wD_qqblpCBg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2534%2F1%2ALdN5sPdgDL0wD_qqblpCBg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 20: Overview of our state machine.&lt;/p&gt;

&lt;p&gt;We use the &lt;a href="https://docs.godotengine.org/en/stable/tutorials/animation/animation_tree.html" rel="noopener noreferrer"&gt;AnimationTree&lt;/a&gt; node to add a State Machine. It’s used to manage different animations and how they blend together based on certain parameters or conditions. Let’s add this node to our Player scene tree. Make sure to add it to your node hierarchy where your AnimationPlayer is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AovqufBZD8ECq08daVzeNMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AovqufBZD8ECq08daVzeNMg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see that it too has a warning next to it, and that is because we have to give it a root animation node. The root animation node determines the starting point of the animation playing, and it can be one of several types of nodes that handle animation data in different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AnimationRootNode:&lt;/strong&gt; This is the base node type for an animation tree. It doesn’t do anything on its own but serves as a container for more specialized animation nodes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AnimationNodeBlendTree:&lt;/strong&gt; This is a complex node that can contain various other nodes to create intricate blends and state machines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AnimationNodeBlendSpace1D/AnimationNodeBlendSpace2D:&lt;/strong&gt; These nodes allow you to blend animations along one or two axes respectively, typically used for blending different locomotion animations like walking, running, and sprinting based on parameters like speed or direction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AnimationNodeStateMachine:&lt;/strong&gt; This node lets you create a state machine for your animations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AnimationNodeAnimation:&lt;/strong&gt; Represents a single animation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Inspector Panel, let’s add a new tree root of type AnimationNodeStateMachine — since we want to play our animations via a state machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AjPNTb9czFxQ8MfLOiaRyNg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AjPNTb9czFxQ8MfLOiaRyNg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A9A_z5b7wdz3zws0-DPScPQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A9A_z5b7wdz3zws0-DPScPQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will create a State Machine in our AnimationTree panel below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AZq31Q0cJtkl1Gouh-PcGJw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AZq31Q0cJtkl1Gouh-PcGJw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also need to assign our AnimationPlayer node to our AnimationTree node’s “Anim Player” property, because we want to access the animations that we added to it in our state machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8cJPUcbFcPnzXhIy3YS2CA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8cJPUcbFcPnzXhIy3YS2CA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, in our state machine below, let’s add our three animations. Select the “Add Node” tool above, and then click anywhere in your state machine panel to add an Animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgQFGLCXyuOD0KjTjVTHZng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AgQFGLCXyuOD0KjTjVTHZng.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AoCRNyjUmWE6YbNxuh2l3VA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AoCRNyjUmWE6YbNxuh2l3VA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AUB3t0ZardDkCL-M4Wptpvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AUB3t0ZardDkCL-M4Wptpvw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can move them around with the select tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AmCEQB_sFyx0QDMs6dCYmsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AmCEQB_sFyx0QDMs6dCYmsw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2346%2F1%2AnFLXj8_yjrzYOHqBLcUjAQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2346%2F1%2AnFLXj8_yjrzYOHqBLcUjAQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the “Transition” tool we can add connections between our animation nodes. This will state which animation plays after the other. Here’s what each transition type generally means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immediate:&lt;/strong&gt; The new animation starts playing immediately, overriding the current one without any blending. The switch is abrupt, and the current animation stops at the point it is in when the transition is triggered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sync:&lt;/strong&gt; This transition type starts the new animation in a way that is synchronized with the current animation. For example, if you’re transitioning from a walk cycle to a run cycle, the transition will start at a point in the run cycle that matches the current position in the walk cycle. This helps maintain continuity in movements, especially for looping animations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;At End:&lt;/strong&gt; With this transition, the new animation will only start after the current one has finished playing. This is useful for non-looping animations where you want the entire sequence to complete before moving on to the next one, such as an attack animation followed by a return to an idle pose.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AJrN4alOKeU0PldEyqKC-HA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AJrN4alOKeU0PldEyqKC-HA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Al7vthBgl8wnmuRQxtpQmqQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Al7vthBgl8wnmuRQxtpQmqQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want the switch from Start to Idle to be immediate, because when our level loads, we immediately want our player to be in an “idle” or waiting state. If you select the line, you can also change the transition switch in the Inspector Panel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A_b6dslPT1lkEJ0W-czhFgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A_b6dslPT1lkEJ0W-czhFgg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AcnnilYBlmVVNaRWz6k0_fQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AcnnilYBlmVVNaRWz6k0_fQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From Idle to Running, we want to add a transition with a switch type of “Sync”, because we smoothly want to transition from our idle to our running animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8X2O0CWM-pMndSRTZIpiyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8X2O0CWM-pMndSRTZIpiyw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AZZfi-MiwcGBv8Kou9t2S-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AZZfi-MiwcGBv8Kou9t2S-Q.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then add an immediate switch back to our Idle animation, because if we stop running, we will immediately return to idle and end the game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Av5NxPVmTFnPeFMTsyN-HeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Av5NxPVmTFnPeFMTsyN-HeQ.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A_Mfo5HNMTeO5O_UrjeUhSg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A_Mfo5HNMTeO5O_UrjeUhSg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We only want to move from Idle to Running if a certain condition is being met. This condition is when our game starts. Our game will start when the player presses ENTER. We can define this condition by selecting our animation transition line between Idle to Running, and in the Inspector Panel, underneath Advance &amp;gt; Expression, giving it a condition. In our case, we will give it the expression “game_starts”. This is a boolean expression that evaluates to true or false based on game logic. This condition would be set to true in our code when we start our game, and false when we complete or fail the level.&lt;/p&gt;

&lt;p&gt;Select the transition between Idle → Running and add the expression “game_starts”. Remember, we will set this value to true/false in our code later on, so if it’s true, the running animation will play.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AYUizCeL5mCF8rPD-o9kWHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AYUizCeL5mCF8rPD-o9kWHg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ANFLhro7CtEGiGuPYrTe0tA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ANFLhro7CtEGiGuPYrTe0tA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the game is over, so our “game_starts” boolean is set to false later on in the code, then we will transition from Running to Idle. Select the transition between Running → Idle and add the expression “not game_starts”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A_y5PQGR6yjBEmEEsaD4noA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A_y5PQGR6yjBEmEEsaD4noA.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AielJ95O754taOxraja-HZA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AielJ95O754taOxraja-HZA.png" alt="Godot 3D Endless Runner" width="587" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also want our Idle to Running animation to be smoother as it syncs from one state to the next. To do this, we need to give it an xfade_time. “Xfade time” refers to “crossfade time,” which is a setting used during animation transitions to define the duration over which two animations blend into each other. When transitioning from one animation to another, rather than abruptly switching from the first animation to the second, a crossfade will smoothly interpolate between the two.&lt;/p&gt;

&lt;p&gt;Getting the right xfade_time requires playing around with the transitions as the right length of xfade time can depend on the specific animations and the context within the game. Select the Select the transition between Idle → Running and change the xfade_time to 0.3 seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AYUizCeL5mCF8rPD-o9kWHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AYUizCeL5mCF8rPD-o9kWHg.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A3PIY46si_UWTOQ59ev9A-w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A3PIY46si_UWTOQ59ev9A-w.png" alt="Godot 3D Endless Runner" width="588" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you press the play icon on your Running animation, the animation transition should be smooth, but if you press play on your Idle animation, the transition should be immediate. Now, let’s add our Jump animation transitions. We will add a “Sync” transition both to and from the Running animation to the Jump animation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AfWsQ6ld6xeFD_0pR9kyeOw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AfWsQ6ld6xeFD_0pR9kyeOw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will also add an Immediate transition from our Jump to our Idle, with the expression “not game_starts”, because if we die or complete the level with jumping, we want to immediately go back to idle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AqhnQomaexYUQZ1Y9luNdnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AqhnQomaexYUQZ1Y9luNdnw.png" alt="Godot 3D Endless Runner" width="427" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A2SkDOGbwIthIicS1gDb-aA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A2SkDOGbwIthIicS1gDb-aA.png" alt="Godot 3D Endless Runner" width="588" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From Running → Jump, we will change the xfade_time to 0.3 seconds, and we will give it the expression “is_jumping”. This is another boolean that we will set up in our code, which will play the jump animation if true, and play the running animation if false.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AkmHKTJH1qvULGlWjtQdplg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AkmHKTJH1qvULGlWjtQdplg.png" alt="Godot 3D Endless Runner" width="582" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, after jumping, we will immediately play the running animation without an expression. Change the xfade_time from Jump → Running to 1 second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AqPzFPi0-qwKthSp46G7y9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AqPzFPi0-qwKthSp46G7y9A.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there we have our animations, animation state, and player skeleton set up. In the next part, we will set up our player camera and movement, so that we can see these animations in action.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unlock the Series!
&lt;/h2&gt;

&lt;p&gt;This series will be turned into a video series on my YouTube channel, but if you like this series and would like to support me, you could &lt;a href="https://ko-fi.com/christinedevs" rel="noopener noreferrer"&gt;donate&lt;/a&gt; any amount to my KoFi shop or you could &lt;a href="https://ko-fi.com/s/1b4909fcd3" rel="noopener noreferrer"&gt;purchase the offline PDF&lt;/a&gt; for $4 that has the entire series in one on-the-go booklet!&lt;/p&gt;

&lt;p&gt;This PDF gives lifelong access to the full, offline version of the “&lt;strong&gt;Learn Godot&lt;/strong&gt;” PDF booklet. This is a 291-page document that contains all the tutorials of this series in a sequenced format, plus you get dedicated help from me if you ever get stuck or need advice. This means you don’t have to wait for me to release the next part of the tutorial series on YouTube, Dev.to or Medium. You can just move on and continue the tutorial at your own pace — anytime and anywhere!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3090%2F1%2AXtlKlCvBDZFbKV8ey3WKhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3090%2F1%2AXtlKlCvBDZFbKV8ey3WKhw.png" alt="Godot 3D Endless Runner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This book will be updated continuously to fix newly discovered bugs, or to fix compatibility issues with newer versions of Godot 4.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>godotengine</category>
      <category>gamedev</category>
      <category>tutorial</category>
      <category>3d</category>
    </item>
  </channel>
</rss>
