Skip to content

Godot Engine

Created: 2020-04-21 08:38:17 -0700 Modified: 2020-07-12 21:44:10 -0700

  • They have a step-by-step getting-started guide here
  • If you don’t want an extra console window when you start the engine, then start it from an existing CMD
  • Visual assets like sprites or 3D models are typically provided by sites like OpenGameArt or itch.io
  • To measure the framerate of a particular scene, play the scene/game, click “Debugger” in the bottom panel, then click “Monitor” and show the FPS. You can disable vsync in the Project Settings if you want it to be uncapped.
  • The building blocks in Godot are nodes, and they form scenes, and scenes can be instanced just like a node so that you manage all of the components more easily.
    • When modifying instances of a scene, you’re modifying just that instance except in the case of shared resources like a material. In that case, making a new material will just affect the single instance. If you want to alter the material’s properties without making a new one, then select “Make Unique” using the arrow next to the resource:

  • When a modification from the source scene exists, you’ll see a gray “revert” button:

  • When saving anything, you can only save to the project itself, so you’ll see special paths like res:// (reference).
  • Project settings are saved to project.godot, but the editor has a GUI for it via Project → Project settings.
    • You can also save custom properties here for use in your game if you want (sort of like environment variables)
  • Design language: Godot says that their design language is what separates them from other game engines (reference). They say to apply these steps
    • List every entity that your game has that would be visible to a player (e.g. projectiles, players, features like a store)
    • Draw a diagram indicating “ownership”
    • Make scenes out of each entity represented
  • They support four scripting languages: GDScript, VisualScript, C#, and C++.
  • Localization is supported directly through the editor (see Project Settings → Localization). If you dynamically set up a string through a script, then you’ll need to use the tr function.
  • To add arbitrary keyboard keys as input, go to Project → Project Settings → Input Map → Add. It’s easy to set up.
  • There’s a concept of groups that you can use for ease of coding in your game. This can be done through scripting or through the UI itself. A group could be for something like alerting enemies that you’ve entered their zone (reference).
    • add_to_group(“players”)
    • is_in_group(“players”)
  • Basics of scripts
    • If you ever have a scene with just a single node, and that node has a script, then the scene doesn’t really need to exist; you could instead just make a member variable whose type is the same as the script, e.g. var stats:Stats = Stats.new(starting_stats)
    • You can only have one script per node.
  • Folder structure (this is not enforced at all, but this seems like a good convention)
    • root
      • assets
        • sprites
        • fonts
        • audio
      • scripts
      • scenes
  • If you want to scale your entire game, I don’t think Project → Project Settings → Display → Window → Stretch → Shrink is a good idea because you may end up chopping off parts of your UI/game. Instead, use Project → Project Settings → Display → Window → Size → Test Width / Height. This will change the size of the window, not the viewport. You may also want to change the Stretch properties so that you scale appropriately.
    • Beyond that, you can add a Camera and modify its zoom property.
  • In general, you’ll want a Sprite to be a child of its RigidBody2D or Area2D.
  • Most issues that you run into with the editor itself can usually be fixed by going back to the Project List (ctrl+shift+Q) rather than restarting Godot completely.
  • If you want to instantiate a scene and still modify its children, e.g. to customize a collider, you can right-click the instantiated scene and toggle “Editable Children”.
  • Tween easings don’t always exactly match easings.net, so someone made a chart
  • If you make changes to the workspace or a particular node while the game is running, then it’ll persist those changes even after the game has stopped. If you don’t want this behavior, then you’ll need to click “Remote” when the game is running and make the changes through the inspector, not the workspace (the workspace always seems to make changes locally).

  • If you have lots of collisions going on (e.g. a bullet-dodging game) use circles for all collisions since they’re fast. If something is more rectangular in nature, draw many circles for it.
  • The collision layer is a bitmask of what an object is considered to be. The collision mask is a bitmask of what an object scans. “A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A.” (reference)
    • You can give your collision layers friendly names via Project Settings → General → Layer Names → 2D Physics
  • For a RigidBody2D to be able to collide physically and also have a function to detect collision, both contact_monitor and contacts_reported must be set correctly (true and >0 respectively).
  • You can generate a CollisionPolygon2D from a sprite automatically (reference)
    • Select a sprite in the scene tree
    • Click “Sprite” toward the top of the editor
    • The result is something like this:
    • These may not be performant unless you have very few of them.
  • Always, always, always make your collision-handling “parent” like Area2D/KinematicBody2D contain your sprites. The reason why is because the body is what’s detecting collisions, so if it’s a child of a sprite, then you’ll need extra code to move the sprite as the body gets adjusted.
  • You can more easily edit the layers by clicking the triple dots so that you don’t have to hover over the graphical representation:

  • To set one-way collision on a tile map, see these instructions
  • Tilemap steps (reference)
    • Make a new scene
    • Ctrl+A → TileMap
    • In the Inspector for the TileMap
      • Set cell properties to the tilesize
        • Note: this does not customize the grid itself that shows in purple-ish in the picture below:

  • As you can see, the tiles don’t align with the grid itself. To configure that, you first have to select a tile (click “new single tile”, click the magnet to enable snapping, then drag any selection). At that point, the inspector will show you the snap options where you can configure the step size (reference).

  • Make a new TileSet

  • Edit the TileSet. You’ll see the bottom panel change.

  • Drag your spritesheet into the left side of the bottom panel

  • Click “New Single Tile” and the magnet to snap to the grid, then click a tile.

  • Name your tile in the right side if you want. This is really important because at least at the time of writing, it’s really hard to tell what you’re editing.

  • At this point, if you click your TileMap node in the scene view and then start drawing tiles using the panel on the right

    • ”New Atlas” is how you can use the whole spritesheet as tiles.
  • Note: you can only set a collision layer at the level of a whole TileMap, not for individual tiles.

  • Click “New Autotile” and drag a contiguous region around your tiles
  • Click “Bitmask” and indicate which quadrants are “filled” (see “bitmask explanation” for an explanation):

  • It’s possible to use a 3x3 grid for more control. You’ll find it in the Inspector → Selected Tile → Autotile Bitmask (reference):

  • Here’s an example of a 3x3 (minimal), although I probably didn’t fill everything in correctly:

Remember, they’re not magic! Godot is just connecting shapes that it can match from the bitmasks that you set up. I hastily annotated a small map with red squares to represent the bitmasks:

Suppose we never set up a bitmask for this ”+” shape that you see in the bottom middle:

The map would go from this:

…to this:

(it’s subtle, but you can see the black pixels at the corners of the middle tile have disappeared since Godot no longer found a ”+” connector)

  • Godot is…
    • Free
    • Open-source
  • Godot’s design philosophy from a coding standpoint is different from other editors (reference)
  • Spritesheets can be done by just loading a particular region of a sprite. This can be done through the “Region” section of the Inspector or via code.

func _ready():
set_region(true)
set_region_rect(Rect2(0,64,32,32))
  • F1-F3: select different workspaces (2D, 3D, Script)
  • Shift+F1: access documentation directly in the game
  • Ctrl+A: add node
    • After adding the node, pressing Enter on it will rename it.
  • F5: play game (this starts with the default scene, which is configured in Project settings → Application → Run → Main scene)
  • F6: play scene
  • F8: stop scene
  • Ctrl+D: duplicate node
  • Ctrl+click (a line in a script): bring up references in the editor directly
  • Ctrl+shift+O: quick-open scene
  • Ctrl+alt+O: quick-open script

I don’t know what caused this, but I had to restart the editor to fix it. Don’t just assume that print(“hit this code”) isn’t being hit just because you don’t see the log.

The reference links suggest that you may have disabled stdout through the project settings.

ViewportContainer not rendering children until manually modifying a property

Section titled ViewportContainer not rendering children until manually modifying a property

This happened to me when I had this code:

add_child(viewport_container)
viewport_container.add_child(viewport)
viewport.add_child(gameplay_scene)

The problem is that I was adding the children to the ViewportContainer after adding the ViewportContainer to the scene tree. I just put the first line at the end and it worked.

E.g. this:

Just enable “Use Pixel Snap” in the Project Settings to fix this.

Note that if you’re only seeing this for an HTML export, then you likely have to use GLES 3.0 instead of 2.0.

E.g. this

To fix this, click your spritesheet in the FileSystem tab, then at the upper left next to “Scene”, you’ll see “Import”. Click “Import”, turn “Filter” off, then click “Reimport”.