reCAPTCHA WAF Session Token

Targeting the Steam Deck with Godot

Embark on an exhilarating gaming journey with the perfect pairing: Godot, the versatile and user-friendly open-source game engine, and the Steam Deck, an exciting handheld gaming device by Valve. This dynamic duo opens up a world of possibilities, empowering game developers and enthusiasts alike to unleash their creativity and experience gaming on the move like never before!

Note: If you’re new to Godot, I recommend checking out my Getting Started guide for a quick introduction.

In this tutorial, I’ll guide you through the process of preparing a Godot project specifically for the Steam Deck, sharing valuable tips along the way. The Steam Deck, developed by Valve, is a handheld gaming device that essentially functions as a portable PC, enabling you to enjoy your Steam library while on the move. With handheld gaming devices gaining immense popularity, developing for the Steam Deck can open doors to exciting opportunities. Godot, an open-source game engine, is gaining recognition for its user-friendly interface and powerful features. This makes it an ideal choice for creating both 2D and 3D games.

Getting Started

You can download the materials for this tutorials via the Download Materials link at the top and bottom of this page.
To follow along, you’ll need the following:

  • Godot installed on your computer
  • A Steam Deck to push the build to
  • (optional) A gamepad to set up and test the input in Godot

After completing this tutorial, you’ll be familiar with:

  • Understanding the Steam Deck hardware
  • Setting up your Godot project for the Steam Deck
  • Detecting the Steam Deck
  • Handling input
  • Game performance considerations and testing

Understanding the Steam Deck Hardware

Before delving into Godot, it’s a good idea to take a closer look at what makes the Steam Deck tick.


Here’s an overview of the Steam Deck’s specifications:

  • CPU: Custom Zen 2 AMD APU
  • GPU: AMD RDNA 2 “Van Gogh”
  • RAM: 16 GB LPDDR5 on-board RAM
  • Screen: 7-inch touchscreen with a 16:10 aspect ratio, 1280×800 resolution
  • Input Controls: Xbox controller buttons, bumpers, triggers and D-pad + trackpads and touchscreen
  • Connectivity: USB-C, Bluetooth, Wi-Fi
  • Battery: 40 watt-hour (2-8 hours of gameplay)
  • Storage: 64 GB eMMC or 256-512 GB NVMe SSD
  • Operating System: SteamOS (KDE Linux)
  • Price: $399-$649

Considerations for Game Development

You might be wondering what all of this means in the context of game development.

For a small device at an affordable price, the Steam Deck packs a punch. The Steam Deck is a lot more powerful than the Nintendo Switch, but not on par with modern desktops. If you want to compare it to a gaming PC, it offers about the same performance as a GTX 1050 or an AMD Radeon RX 560. This means you’ll need to consider its limitations when developing for it. Simple games will work fine, but more complex games will need to be optimized in order to run smoothly.

The small screen and low resolution make it difficult to read fine textures and character animations. You should enlarge UI elements like text to make them easier to read. This is a good practice anyway in terms of accessibility.

A great upside is the Steam Deck’s controller layout. If your game supports Xbox controller input, it will be compatible with the Steam Deck without any additional work. Players can also customize the layout to their liking using the Steam Deck’s controller settings, which can map keyboard, gamepad and mouse input to the device’s controls. Some people have even made MMORPGs work with the Steam Deck this way, which are known for their abundant keyboard shortcuts.

Because the Steam Deck has a battery, you’ll want allow for shorter play sessions and optimize your game for battery life. Ideally, the player can tweak the settings between battery life and performance.

I won’t be covering how to tackle all of these considerations in this tutorial, but make sure to keep them in mind. It’s a good idea to test how well your game runs on the Steam Deck before optimizing it. You might be surprised by how well it runs without any adjustments.

Up next is taking a look at the sample project.

Exploring the Project

This project is a small 3D car driving sandbox inspired by Micro Machines. There’s a track and a few mountains to drive on.

Running the Project

Start by opening the starter project in Godot. You should see a 3D scene with a car.

Press F5 to run the project and drive the car around. Here are the controls:

  • A or Left: Steer left
  • D or Right: Steer right
  • W, Up or Space: Accelerate
  • S or Down: Brake
  • Ctrl/Cmd: Switch the camera view

Driving car around

After testing the project, take a look at the Scene dock of the level scene.

Level nodes

Here’s a quick rundown:

  • CameraManager: A regular node with a script attached to switch the active camera
  • WorldEnvironment: The lightning settings for the level
  • DirectionalLight3D: A directional light that acts as a virtual sun
  • BirdsEyeCamera: A camera that follows the car from above
  • LevelModel: The 3D model and colliders that represents the level
  • Car: The car scene
  • CanvasLayer: The canvas on which you can add Control nodes to make a user interface. There’s already a label here with a transparent background.

You’ll build upon these nodes throughout the tutorial.

Project Settings

Out of the box, new Godot projects are ready to be run on the Steam Deck. However, there’s one setting I recommend changing during development: the viewport size. The default value is set to 1152×648, which doesn’t match the 1280×800 resolution of the Steam Deck. By setting the viewport size to match, it’s easier to preview what the game will look like on the actual device.

To change the viewport size, open the Project Settings by selecting Project ▸ Project Settings.

Project Settings

Now select Window on the left.


Next, set the Viewport Width to 1280 and Viewport Height to 800.

Viewport width 1280 height 800

Finally, click the Close button to close the window. Open the 2D screen using the tabs at the top, and you’ll see a blue outline in the center screen if you zoom out. These are the bounds of the screen you’ll be working in.

Blue outline in viewport

With that out of the way, it’s time to get to the fun parts!

Detecting the Steam Deck

Godot doesn’t have a built-in variable to determine if a device is a Steam Deck. What it does have is a set of functions that can read both the software and hardware information from the device. From this information, you can detect if the device is a Steam Deck if you know what to look for. To do that, you can add a script to the info label at the top left which will display the information and detect if your project is running on a Steam Deck.

First, select CanvasLayer ▸ Info ▸ MarginContainer ▸ SystemInfoLabel in the Scene dock.


Now attach a new script to the label, name it and place it in the scripts folder.

Label path

This should automatically open the Script screen and display the new script. To read the system information and add it to the label, replace the _ready function with the following:

func _ready() -> void:
    self.text = "" # 1

    self.text += "OS: " + OS.get_name() + "\n" # 2
    self.text += "Distro: " + OS.get_distribution_name() + "\n" # 3
    self.text += "CPU: " + OS.get_processor_name() + "\n" # 4
    self.text += "GPU: " + RenderingServer.get_rendering_device().get_device_name() + "\n" # 5

Here’s a summary of what this does:

  1. Clear the text of the label
  2. Use OS.get_name() to return the name of the operating system the build targets. Confusingly, this won’t always match the name of the actual OS. The \n adds a new line at the end.
  3. OS.get_distribution_name() returns the name of the distribution. On Windows (and Proton), this is “Windows”. On Linux, this is the name of the distribution, such as “Ubuntu” or “SteamOS”.
  4. The OS.get_processor_name() function returns the name of the CPU.
  5. RenderingServer.get_rendering_device().get_device_name() returns the name of the GPU.

Now press F5 to save the script and run the project. You should now see the system information in the info label

Main pc System Specs

If you would export and run this project on your Steam Deck at this point, you’ll see that the system info is filled in correctly.
Here’s the result with a native Linux build:

Steam Deck info on Linux

And here’s the result with a Windows build:

Steam Deck info on Windows

I’ll cover how to export and run this project on the Steam Deck later on in this tutorial. For now, the most important thing to take away is what the Steam Deck reports as its CPU and GPU:

  • CPU: AMD Custom APU 0405
  • GPU: AMD Custom GPU 0405 (RADV VANGOGH)

Based on this information, you can detect if your project is running on a Steam Deck. To do so, add the following function to the script:

func _is_steam_deck() -> bool: # 1
    if RenderingServer.get_rendering_device().get_device_name().contains("RADV VANGOGH") \
    or OS.get_processor_name().contains("AMD CUSTOM APU 0405"): # 2
        return true
    else: # 3
        return false

This function will return true if the Steam Deck is detected, and false otherwise:

  1. This is a function named _is_steam_deck which returns a boolean value.
  2. If the name of the GPU contains the string “RADV VANGOGH” or the CPU name contains the string “AMD CUSTOM APU 0405”, it returns true.
  3. Otherwise, it returns false.

Now add this line to the _ready function:

    self.text += "Steam Deck: " + str(_is_steam_deck()) + "\n"

This will show true or false depending on if the project is running on a Steam Deck. Run the project again to see the result.

Steam Deck false

On an actual Steam Deck, this will be true of course!
Here are some suggestions on what you can do with this information:

  • Enable gamepad support
  • Show button prompts and other graphics specific to the Steam Deck
  • Automatically adjust performance settings to run optimally
  • Move and resize UI elements for better readability
  • Gather analytics to improve the project’s performance

Handling Input

The Steam Deck has input controls and a touchscreen. In this section you’ll learn how to get the input from the Steam Deck and use it in your project.

Input Map Setup

The input from the Steam Deck’s controller can be mapped in Godot as if you were using an Xbox controller.
To start off, take a look at the current actions in the input map by selecting Project ▸ Project Settings ▸ Input Map.


The actions defined in the input map are:

  • accelerate
  • brake
  • left
  • right
  • switch_camera

For each of these actions, you’ll need to add a new gamepad event to support input from a game controller. Here are the mappings I’ll be using:

  • accelerate : Right trigger
  • brake : Left trigger
  • left : Left analog stick left
  • right : Left analog stick right
  • switch_camera : Y button

You can change these mappings as you prefer, or add extra ones. To map a new event to an action, click the + button next to the action’s name.

Plus button next to accelerate

Next, either press or move the input you want to bind to the action on your gamepad. If you don’t have a gamepad, you can select the event under Joypad Buttons or Joypad Axes. For the accelerate action for example, you’d press the right trigger.

Pressing right trigger

Now click the OK button at the bottom left to confirm adding the event. You’ll now see that the event has been added to the input map.

Added event

Now do the same for the other actions until they all have gamepad events.

All events

To test if the gamepad events are working, run the project again while using a gamepad.

Test drive

Great! That’s all you need to do to support the Steam Deck’s controller. Next up is using the touchscreen.

Touchscreen Input

Although the Steam Deck has a touchscreen, it shouldn’t be the primary way to interact with your game due to the small screen size its lower sensitivity compared to a smartphone. However, you can add simple buttons or detect motion events as an optional feature.

As an example, you’ll be adding a button to the corner of the screen to switch the camera view.

Camera button

To add the button, start by adding a Button node to CanvasLayer by right-clicking the CanvasLayer node and selecting Add Child Node. Next, search for “Button” in the search bar at the top, select Button and click the Create button to add it.

Add button

This should’ve added a new Button node below the CanvasLayer node.


Select this new button and rename it to CameraSwitchButton by right-clicking it and selecting Rename or by pressing F2. Now switch to the 2D mode to see selection box around the button at the top left. You may have to zoom in to get a better view.

Selected button

At the moment, there’s not much to see. To change that, drag the camera_switch.png image from the sprites folder in the FileSystem dock onto the Icon field in the Inspector.

Drag button icon

The button will now be a lot larger, with an icon in the middle.

Icon in button

To get the button to the top right instead of the top left, change its anchor preset to Top Right via the Anchor dropdown in the toolbar.

Top Right Anchor

This moves the button to the top right as expected. To give it a small offset from the edges of the screen, hold down Shift and press the left arrow key on your keyboard followed by the down arrow key. This creates a few pixels of space from the edges.

Move button away from edges

To prevent the button from being pressed by accident when pressing keyboard or gamepad button, it’s best to disable the focus mode of the button. You can do this by scrolling down in the Inspector, expanding Focus under the Control section and selecting None from the Mode dropdown.

Change focus mode to none

Great! All that’s left for this button is to hook up its pressed signal to the switch_camera function of the CameraManager node. Switch to the Node tab in the Inspector and double-click the pressed() signal.

Pressed signal

This opens a signal connection dialog window where you can choose a function to call when the button is pressed. Now select the CameraManager node and click the Pick button. This will open a list of functions that can be called.

CameraManager Pick

Next, select the switch_camera function and click the OK button.

switch camera function

Back in the signal connection dialog, click the Connect button at the bottom to finish the connection.
Here’s what the switch_camera function looks like:

func switch_camera() -> void:
    if birds_eye_camera.current:
        behind_car_camera.current = true
        behind_car_camera.current = false

This toggles the active camera between the behind the car camera and the birds eye camera. With the button all set up, it’s time for another test drive!
Fire up the project again using F5 and test if the button works as expected.

Toggle camera view

The project is now finished! Time to test it on a real Steam Deck.

Exporting Builds

You’ll be creating both a Windows and a Linux build for the Steam Deck. This makes it easy to compare what type of build will offer the best performance.
First off, select Project ▸ Export… in the top menu to open the Export Presets menu.

Select Export

Now click the Add… button at the top and add a Linux/X11 export preset.

Add linux preset

Note: If you get an error at the bottom saying “No export template found”, click the Manage Export Templates link and download the template via the Export Template Manager.

Now set the Export Path to any folder on your PC, ideally a folder that syncs to the Steam Deck.

Set export path

To add the Windows export preset, click the Add… button again and select Windows Desktop this time. Next, select an Export Path just as you did for the Linux preset.
Now click the Export All… button at the bottom right to export the project using both presets. For the export mode, choose Debug. This will build both a Windows and a Linux build in the folders you specified.

Export all and debug

With the project exported, you can now test them on the Steam Deck. If you’re not sure how to transfer and run your builds to the Steam Deck, take a look at the How to Transfer Game Builds to a Steam Deck article.

Game Performance

The Steam Deck comes with a nifty performance overlay built-in that shows you how hard the CPU and GPU are working. By examining the information this overlay provides, you can get a better understanding of how your game is performing.

Running the Linux Build

To start off, run the native Linux build first and test if everything is working correctly. You should be able to control the car using the built-in gamepad and clicking the camera button on the screen switches the camera view. The system info should say you’re running the project on a Linux-based OS named SteamOS and the Steam Deck flag should be set to true.

Linux build info

Now enable the performance overlay by clicking the three dotted button at the bottom right of your Steam Deck and selecting the battery icon in the Quick Access menu. From here, slide the Performance Overlay Level to 4.

Set performance overlay

Next, take a look at the left side of the screen to see all the performance information you could ever want.

Performance info

It might be a bit hard to see what’s going on because of the background, but here’s a quick overview from top to bottom:

  • GPU: GPU usage, temperature, clock speed and power draw
  • CPU: CPU usage, temperature, clock speed and power draw
  • CPU cores: The usage per CPU core, with its clock speed
  • VRAM: The amount of VRAM used by the GPU to render the game
  • RAM: Amount of RAM used by the game
  • BATT: The amount of battery life left, the total power draw and the approximate time left before the battery runs out
  • FAN: The fan speed in rotations per minute
  • FSR: Whether FSR (Fidelity Super Resolution) is enabled or not
  • GAMESCOPE: The frame time and frame count

The most important metric out of all of these is the frame time. If the green line is flat all the time, then your game will feel smooth as it’ll run at a stable 60 FPS. However, if the green line is constantly jumping up and down, then your game will feel choppy and laggy. There’s no way to totally avoid some choppiness when instantiating new scenes and while the shaders are compiling, but during the main game loop, the frame rate should be stable.

To get an idea of how graphically demanding your game is, take a look at the GPU clock speed. The higher the number, the more demanding the game is. The Steam Deck has a tendency to try to use the least amount of power possible, so it clocks down its 1.6 GHz (1600MHz) GPU whenever it can. In the case of the car game, it tends to hover between 1050 and 1100 MHz.
To know the amount of leeway you have in terms of graphical performance, you can manually set the GPU clock speed via the performance settings. Press the three dotted button again and scroll down to Manual GPU Clock Control in the Performance section. Now check the checkbox next Manual GPU Clock Control and slide GPU Clock Frequency to 1600. This will lock the GPU clock speed to its highest possible value for optimal performance.

Set GPU clock 1600

If you now exit the menu and take another look at the GPU clock, you’ll notice it’s now set to 1600MHz.

GPU clock 1600

The percentage above the clock speed is now much more valuable, as this indicates how much your game is using the GPU in simple terms. As the car game isn’t optimized in any way, the GPU utilization is somewhere between 58% and 70% most of the time, which is surprisingly high for such a simple game.

The CPU usage is easier to spot, as you just need to look at the CPU usage percentage. The higher the number, the more demanding the game is in terms of CPU usage.

CPU usage

Now exit the Linux build of the game as it’s time to move over to the Windows build.

Running the Windows Build

Start up the Windows build and take a look at the system info at the top left. Instead showing the actual OS, it says the game is running inside Windows. The Steam Deck flag is set to true though as expected.

Windows build info

The reason why it says Windows here instead of Linux like with the other build is because Windows executables are run inside a Proton compatibility layer. Games running like this will “think” they’re running on a Windows machine. Some games run better under Proton than their native counterparts, while some won’t work at all. It’s best to test out your games thoroughly before deciding what version you want to recommend for the Steam Deck.

Now lock the GPU clock to 1600 again and inspect the performance of the Windows build.

Windows performance

The game is running almost identical to the Linux build, so in this case the native Linux build might be the best option. It’s a good idea to keep testing both types of builds as your game increases in complexity.

Where to Go From Here?

Congratulations! You’ve set up a Godot project for the Steam Deck, exported it and did some basic performance testing. You can download the final project at the top or bottom of this tutorial.

If you’re stuck, don’t hesitate to seek help from the Godot community through their Discord, forums, or other platforms. You can also reach out via the Kodeco Discord and by joining the discussion below.
If you create something cool for the Steam Deck using Godot, don’t forget to share it!

Source link

Leave a Reply

Your email address will not be published. Required fields are marked *

WP Twitter Auto Publish Powered By :