Skip to content

Add a built-in virtual controller#116716

Open
Kazox61 wants to merge 9 commits intogodotengine:masterfrom
Kazox61:virtual-controller
Open

Add a built-in virtual controller#116716
Kazox61 wants to merge 9 commits intogodotengine:masterfrom
Kazox61:virtual-controller

Conversation

@Kazox61
Copy link
Copy Markdown
Contributor

@Kazox61 Kazox61 commented Feb 24, 2026

Closes godotengine/godot-proposals#11193

The Virtual Controller creates Joypad-Motion and -Button events. This enables testing games on mobile devices if you setup Joypad controls in the Inputmap.

2026-02-24.14-45-00.mp4

TODO:

@Kazox61 Kazox61 requested review from a team as code owners February 24, 2026 14:09
@@ -257,6 +260,7 @@ void VirtualJoystick::_bind_methods() {
ADD_SIGNAL(MethodInfo("released", PropertyInfo(Variant::VECTOR2, "input_vector")));
ADD_SIGNAL(MethodInfo("flicked", PropertyInfo(Variant::VECTOR2, "input_vector")));
ADD_SIGNAL(MethodInfo("flick_canceled"));
ADD_SIGNAL(MethodInfo("motion", PropertyInfo(Variant::VECTOR2, "input_vector")));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"motion" is a bit of a misleading name IMO, it sounds like a property

Comment thread scene/gui/virtual_controller.h
Comment thread scene/gui/virtual_controller.h Outdated
Comment thread scene/gui/virtual_controller.cpp Outdated
@AThousandShips AThousandShips added this to the 4.x milestone Feb 24, 2026
@Ivorforce Ivorforce requested review from a team February 24, 2026 14:30
@Nintorch Nintorch self-requested a review February 24, 2026 15:20
@Nintorch
Copy link
Copy Markdown
Member

Hello! I haven't tested this PR, but so far I think it looks nicely done, good job! :)
The original proposal also mentions having a project setting to toggle the visibility of the virtual joystick, do you think it's a good idea? May I ask if it's possible to make this functionality?

@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Feb 24, 2026

Project Settings or directly from the input singleton? Also currently I m not sure which Node I can use to add the VietualController as Child.

@Nintorch
Copy link
Copy Markdown
Member

Project Settings or directly from the input singleton?

I think having both would be nice, see also #115119 for an example of creating a project setting + Input class property, and #115119 (comment)

@JekSun97
Copy link
Copy Markdown
Contributor

Closes also Add analog joysticks to window Embedding game for android

@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Feb 25, 2026

Should the Virtual Controller only show up when there is a Touchscreen available?

@Kazox61 Kazox61 requested a review from a team as a code owner February 25, 2026 09:16
@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Feb 25, 2026

For pressing multiple buttons at the same time, #110893 is needed to get merged

@Nintorch
Copy link
Copy Markdown
Member

I'm not sure Input class can depend on classes from the scene/ folder.
I think I have an idea on how to fix it, I will try to do that when I have enough free time! :)
Basically, I think we can add the VirtualController node under scene tree root, and make the node itself react to changes in the Input class property.
I'm currently not sure if it's a good approach, but if it works and other maintainers are not against it, we can do that.

@Zireael07
Copy link
Copy Markdown
Contributor

Cameras have nothing to do with input though

Copy link
Copy Markdown
Member

@Nintorch Nintorch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a commit in one of my fork's branch to decouple Input from VirtualController and scene/ files: Nintorch@a931913
In that same commit I also deregistered VirtualController so its nodes can't be created in scenes directly by the user, I'm not currently sure it makes sense to allow that since the current functionality of enabling it through the Input property and a project setting should be enough, unless we want to allow the users to create 2 or more VirtualControllers or allow them to be freely modified. :) (EDIT: I just noticed that you're planning to make VirtualController customizable, in this case it does make sense for its nodes to be created directly by the user, so you can ignore that change by me in my commit! :D)
I also tested the functionality of VirtualController on Windows today. I think it mostly works as expected, except for 2 notes here:

  1. I think when the VirtualController is visible, Godot should register it as a connected joypad, so projects like https://gist.github.com/anthonyec/5342fce79b2b7b22ada748df0ad7f7c0 and joypad functions like Input.get_joy_axis() or Input.is_joy_button_pressed() can also be used with it.
  2. VirtualController is not suited for smaller output sizes at the moment. This can be a problem if it's used for pixel art games.
VirtualController with a regular size Image
VirtualController with a smaller size Image

Otherwise I think it looks nicely done! :)

Comment thread core/input/input.cpp
@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Mar 1, 2026

@Nintorch I added the changes from your branch. I also registered the virtual controller, so the gamepad debugger works.

I noticed that the Dpad Up, Down and Right Button doesn't work. I couldn't find the reason? Did you have the same problem?

2026-03-01.15-56-53.mp4

@Kazox61 Kazox61 force-pushed the virtual-controller branch from 990cc55 to 897ae64 Compare March 1, 2026 15:03
@Nintorch
Copy link
Copy Markdown
Member

Nintorch commented Mar 1, 2026

I did have the same problem with dpad, yes. I'm not exactly sure what's causing it, but I think UI navigation might be messing with it.

I think I found another small bug, VirtualController at the root doesn't respect Camera2D image

This should be an easy fix though, we just first need to create a CanvasLayer at the scene root and then add VirtualController as its child.

Another small suggestion I have is that we may need to separate Enable Virtual Controller project setting into 2:

  1. Enable Virtual Controller: If true, a VirtualController node is created at the scene root, otherwise it's not created by default;
  2. Show Virtual Controller On Startup: If true, the VirtualController created by the project setting above will be shown on the game's startup, otherwise it will be hidden by default. (In this case, we might also need to rename Input.virtual_controller_enabled to Input.virtual_controller_visible and make it not do anything if Enable Virtual Controller is disabled, since the VirtualController isn't created)

The reason for that is that we probably don't want to create this node at the scene root for all Godot games, even the ones that won't use it, and we don't want joypad 0 to always be reserved for VirtualController. What do you think? :)

@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Mar 1, 2026

Calinou suggested using CanvasLayer as a base here: godotengine/godot-proposals#11193 (comment)
Not sure it this has any negative side effects.

I also agree that the VirtualController shouldn't be instantiated for every project. That's why my initial commit created and destroyed always the virtual controller instead of hiding and showing it when enabling.

@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Mar 1, 2026

@Nintorch what would you suggest to fix the problem with smaller output sizes?

@Nintorch
Copy link
Copy Markdown
Member

Nintorch commented Mar 2, 2026

Should the Virtual Controller only show up when there is a Touchscreen available?

Sorry for late reply, I just noticed this question. 😅
I think it should be fine to make it work on other devices too for the purpose of testing the virtual controller.

@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Mar 2, 2026

Also what about the Buttons text? Do we want to have some sort of Icons. Or do we keep the simple text?

@Nintorch
Copy link
Copy Markdown
Member

Nintorch commented Mar 2, 2026

I think having icons by default would be nice, but I feel like we may need to wait for an answer from the usability team to see what they think :)

@Kazox61 Kazox61 force-pushed the virtual-controller branch from b1e0d9d to a9eb624 Compare March 13, 2026 09:40
@Kazox61 Kazox61 requested a review from a team as a code owner March 13, 2026 09:40
@Alex2782
Copy link
Copy Markdown
Member

Alex2782 commented Apr 8, 2026

BaseButton: multitouch support #110893
Even though this PR cannot yet completely replace the TouchScreenButton, it would probably be a prerequisite for the built-in virtual controller.


🐧 Linux / Minimal template (target=template_release, everything disabled) fails.

Can it be reproduced on other platforms as well? (without cache_path)

Building with flags: platform=linuxbsd target=template_release dev_mode=yes module_text_server_fb_enabled=yes modules_enabled_by_default=no module_text_server_fb_enabled=no disable_3d=yes disable_advanced_gui=yes disable_physics_2d=yes disable_physics_3d=yes deprecated=no minizip=no brotli=no accesskit=yes cache_path=/home/runner/work/godot/godot/.scons_cache/ redirect_build_objects=no

/usr/bin/ld: core/libcore.linuxbsd.template_release.x86_64.a(input.linuxbsd.template_release.x86_64.o): in function `Input::set_virtual_controller_enabled(bool)':
input.cpp:(.text+0x32c): undefined reference to `VirtualController::VirtualController()'
collect2: error: ld returned 1 exit status
scons: *** [bin/godot.linuxbsd.template_release.x86_64] Error 1
scons: building terminated because of errors.
INFO: Time elapsed: 00:01:41.49
Error: Process completed with exit code 2.

@m4gr3d m4gr3d requested review from KoBeWi, YeldhamDev and kitbdev April 9, 2026 15:24
@kitbdev
Copy link
Copy Markdown
Contributor

kitbdev commented Apr 9, 2026

Input is in core, so it should never include anything in "scene/".
This is probably why CI is failing, also see #53295.

Copy link
Copy Markdown
Contributor

@m4gr3d m4gr3d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tested the feature; this is a great first step but there are still quite a bit of polish to be done before we consider it done and ready:

  • Multiple buttons cannot be pressed at the same time - fixed by #118608
  • Buttons should highlight on hover / press to show they are being interacted with
  • The virtual controller needs a configuration screen to allow developers to configure to match their game needs:
    • Need an option to hide / show each joystick and buttons
    • Need an option to update the buttons / joysticks contrast in order to make them more visible on light background
    • Need an option to configure the joystick (e.g: inverted / regular), or just expose the virtual joystick configuration options
    • Need an option to map an action to a button press

I think this would be great to land in Godot 4.8 so I've updated the milestone accordingly. @Kazox61 Are you able to drive this PR forward to target a 4.8 release?

@Kazox61
Copy link
Copy Markdown
Contributor Author

Kazox61 commented Apr 16, 2026

Yes I would like to continue. Currently I don't who should be the owner/parent of the VirtualController, since Input is not allowed.

Comment thread main/main.cpp
for (Node *E : to_add) {
sml->get_root()->add_child(E);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated, please restore

@m4gr3d
Copy link
Copy Markdown
Contributor

m4gr3d commented Apr 16, 2026

Yes I would like to continue. Currently I don't who should be the owner/parent of the VirtualController, since Input is not allowed.

@kitbdev Do you have any suggestions?

@kitbdev
Copy link
Copy Markdown
Contributor

kitbdev commented Apr 16, 2026

I really don't know much about this feature, but here's my suggestions.
To show UI from a Project Setting, the functionality should be moved to somewhere else like SceneTree, Window, or Viewport. I don't see any code reason it needs to be in Input, so it should be easy to move. If the controller should only show in the main window, then it probably has to be SceneTree. The closest thing to this situation is probably #79599 .

I don't know if it needs a property in addition to the project setting, but if you really want a property on the Input singleton, it could emit an unexposed signal (prefixed with _) that SceneTree connects to.

Edit: It's been mentioned in the proposal that SceneTree isn't a good fit and I agree, but I don't think we have anywhere else for it. Maybe a new singleton?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add analog joysticks to window Embedding game for android Add a built-in virtual controller for easier game development on mobile devices

9 participants