How can I use multiple joystick at the same time

Godot Version

Godot 4.2

I have a game with a movable player that can choose where to shoot, but when I port my game to android, I can only use one joystick at a time. I have tried to find resources online about indexing the action, but the resources are either confusing or extremely outdated. I want to know how to solve the issue.

Here is the shooting button script, the one for movement is almost identical.

extends Sprite2D

@onready var parent = $“…/”

var pressing = false
var initial_poz: Vector2
@export var max_length = 146
@export var deadzone = 5

func _ready():
max_length *= parent.scale.x

func _process(delta):
if pressing:
if get_global_mouse_position().distance_to(parent.global_position) <= max_length: #
global_position = get_global_mouse_position()
else:
var angle = parent.global_position.angle_to_point(get_global_mouse_position())
global_position.x = parent.global_position.x + cos(angle)*max_length
global_position.y = parent.global_position.y + sin(angle)max_length
if $“…/…/…”.movement_joystick == true:
close_the_gap(delta)
calculateVector()
else:
global_position = lerp(global_position,parent.global_position,delta
50)
parent.posVector = Vector2(0,0)
parent.position = initial_poz + Vector2(-689,333)

func calculateVector():
if abs((global_position.x - parent.global_position.x)) >= deadzone:
parent.posVector.x = (global_position.x - parent.global_position.x) / max_length
if abs((global_position.y - parent.global_position.y)) >= deadzone:
parent.posVector.y = (global_position.y - parent.global_position.y) / max_length

func close_the_gap(delta):
var global_mouse_position = get_global_mouse_position()
parent.global_position = lerp(parent.global_position,global_mouse_position,delta * 5)

func _on_button_button_down():
pressing = true

func _on_button_button_up():
pressing = false

The tree structure (what is important) is like so:

  • Game
    • Player
      • GUI (but i can easely remove this as I have got no code in it)
        • mobile_shooting_joystick
        • mobile_joystick

I don’t know what more information I am supposed to give, as I have no idea how to solve this.

Because the GUI buttons are made for mouse use, using Multi Touch with Android won’t work with any of them. (_on_button_button_down() or _on_button_button_up())

I had this issue myself and used TextureRect instead of buttons.

you connect _gui_input(event). to your player like this

func _on_texture_rect_gui_input(event):
if event is InputEventScreenTouch:
if event.is_pressed():
print(“ButtonTouch”)

Thanks, now they work simultaneously, but, like what other resources on the internet have pointed out, both joysticks point to the same touch, the first one. I don’t know how to solve this problem. I have no idea how I would do an easier solution: let the joysticks point to the closest touch, let alone the complete one.

I cannot just detect if the touch is inside the button as if a setting is true, I want to freely move the joystick.

This is the code for the movement joystick:

extends Sprite2D

@onready var parent = $“…/”

var pressing = false
var initial_poz: Vector2
@export var max_length = 146
@export var deadzone = 5

func _ready():
max_length *= parent.scale.x

func _process(delta):
if pressing:
if get_global_mouse_position().distance_to(parent.global_position) <= max_length: #
global_position = get_global_mouse_position()
else:
var angle = parent.global_position.angle_to_point(get_global_mouse_position())
global_position.x = parent.global_position.x + cos(angle)*max_length
global_position.y = parent.global_position.y + sin(angle)max_length
if $“…/…/…”.movement_joystick == true:
close_the_gap(delta)
calculateVector()
else:
global_position = lerp(global_position,parent.global_position,delta
50)
parent.posVector = Vector2(0,0)
parent.position = initial_poz + Vector2(-689,333)

func calculateVector():
if abs((global_position.x - parent.global_position.x)) >= deadzone:
parent.posVector.x = (global_position.x - parent.global_position.x) / max_length
if abs((global_position.y - parent.global_position.y)) >= deadzone:
parent.posVector.y = (global_position.y - parent.global_position.y) / max_length

func close_the_gap(delta):
var global_mouse_position = get_global_mouse_position()
parent.global_position = lerp(parent.global_position,global_mouse_position,delta * 5)

func _on_touch_screen_button_pressed():
pressing = true

func _on_touch_screen_button_released():
pressing = false

I know that the “global_mouse_position” is the problem here, but I don’t know how to solve it. Please, help me.

Sorry, I mixed up the tabs and answered this question incorrectly; my first response was for someone else’s problem. The problems were similar.
Have you tried this add-on? Virtual joystick for godot it does most of the things you want
also its written in gd-script so you can look at the code to learn more

If you want the index of a touch or drag, you can use

func _input(event):
    if (event is InputEventScreenDrag ):
        if event.is_pressed():
            
            print(event.get_indexed())