Bite-Sized Godot: Easy in-engine screenshots
(Trying something a bit different this time. The video above is a short look at the what and how, whereas this post is a bit more detailed of a breakdown of the video’s contents.)
Taking in-engine screenshots on Godot is quite straightforward, and today I’ll show you the simple setup for doing so I find myself reaching for on pretty much all of my recent projects, including Unto Deepest Depths (go wishlist!).
The benefits of having an in-engine screenshot setup are numerous. A few reasons might be:
- On Windows, Print Screen captures rounded window borders, which is no good for uses like Steam screenshots.
- In-engine screenshots mean you can do fancy scene transitions by capturing what one scene looks like, displaying that image while you load the next scene, and then smoothly fading to the new scene without having to actually have both scenes loaded in the game at the same time.
- You can easily add a photo-mode to your game.
- You can capture the perfect screenshot by auto-triggering the capture when a certain event occurs
So with the why out of the way, let’s look at the how.
Implementation
At a high level, what we need to do is create an Autoloaded script that listens for a given keypress, grabs the output of the game’s viewport, and then saves it to the user’s machine.
Let’s walk through the process in detail.
Setup
Open up your project of choice and update your Input Map (under Project > Project Settings > Input Map) to add an input for taking a screenshot that doesn’t conflict with whatever other inputs you have configured. Then create a script inheriting from the basic Node class and add it as an Autoload so that it will be globally available (under Project > Project Settings > Autoload).
Update this script so that it listens for the input you configured and you’ll be ready to take a screenshot!
# Script for the screenshot autoload
extends Node
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed('screenshot'):
take_screenshot()
func take_screenshot() -> void:
pass
As a quick reminder, all projects have a Viewport present by default that the game is rendered to, so if we grab the contents of this default Viewport, we’ll capture whatever is drawn on screen.
To get a reference to the current viewport, we can call get_viewport() inside of our screenshot script. When called on a Node, this function grabs the closest Viewport in the scene to that Node, which in this case will just be the default Viewport everything gets rendered to since Autoloads sit towards the top of the scene tree.
Once we have a reference to the Viewport, we can grab its contents as a texture with the get_texture() function.
Now we have the Viewport contents in a format that can really be treated like any other kind of texture data, but for now we just want to save this data to disk. The easiest way to do this is to convert the Texture2D data to an Image instance, which has built-in functions for saving to common image formats. We can do the conversion by calling get_image() on our texture data, and then save the data by calling the save_png() function, or the similar functions for other formats if desired, on our Image class and providing the path to save it to.
Coding up all of this results in the following:
extends Node
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed('screenshot'):
take_screenshot()
func take_screenshot() -> void:
get_viewport().get_texture().get_image().save_png('some/local/directory/image.png')
And that’s the basics of taking a screenshot in Godot! Do note that images are saved at the Viewport resolution, and not the window resolution, so if you’re working with a pixel art game, you’ll probably want to resize the saved image, either before hand using Image.resize or after saving, but from here it’s all about improving upon and integrating with your project how you see fit.