Este plugin permite a los desarrolladores gestionar ágilmente las entradas físicas (Inputs) para partidas multijugador local en un mismo PC, ya sean juegos de plataforma cooperativos, de mesa, o de peleas.
En lugar de crear manualmente cientos de eventos en el InputMap usando sufijos extraños como "p0_jump", "p1_jump", etc. este plugin intercepta la conexión de gamepads y asigna un mapeo seguro para evitar "ghosting" e interferencias entre mandos.
- Copia la carpeta
input_multi_device/al directorioaddons/de tu proyecto Godot. - Abre tu proyecto de Godot.
- Ve a
Proyecto>Configuración del Proyecto>Plugins. - Activa el plugin marcando la casilla de verificación en "InputMultiDevice".
- ¡Listo! El entorno ya cuenta con un AutoLoad principal global bajo el nombre
InputMultiDevice.
Puedes ver el plugin en funcionamiento en los siguientes demos técnicos:
| Space Shooter | Menu Options | Platform Demo |
|---|---|---|
![]() |
![]() |
![]() |
| Ver en YouTube | Ver en YouTube | Ver en YouTube |
¿Por qué usar este plugin en lugar de programar la entrada manualmente o usar otras alternativas?
- Escalabilidad sin "InputMap Bloat": En lugar de ensuciar el
InputMapcon cientos de entradas (p0_jump,p1_jump,p2_jump...), el plugin orquesta estas acciones dinámicamente por código. - Aislamiento de Teclado Real: Godot nativo mezcla todos los teclados conectados. Este plugin permite separar físicamente el teclado en dos dispositivos virtuales independientes para multijugador local en una misma máquina sin interferencias.
- Gameplay Agnóstico: Tu código de movimiento es idéntico (
InputMultiDevice.get_vector) sin importar si el jugador usa un DualSense, un mando de Xbox o la mitad de un teclado.
- Arquitectura Orientada a Perfiles (CRUD): A diferencia de otros plugins que solo detectan mandos, este incluye un backend completo para crear, remapear, eliminar y persistir perfiles con nombre (estilo juegos de pelea profesionales).
- Ligero y Extensible: No intenta ser un framework visual pesado. Es un Singleton lógico que puedes conectar a cualquier UI de Lobby o Menú de Opciones en minutos.
- Vibración Optimizada: Enruta el "Rumble" automáticamente al dispositivo correcto y hace bypass silencioso en teclados, evitando excepciones comunes de "Invalid Device ID".
Este plugin abarca todo el ciclo de vida del input en un juego multijugador local:
- Detección Plug & Play: Identificación automática de hardware (Mandos de Xbox, PlayStation, Switch y Teclados) al conectarse, sin reiniciar el juego.
- Unión Universal (Lobby System): Sistema listo para usar que detecta cuándo un jugador quiere unirse a la partida mediante un botón universal (
StartoEnter). - API Híbrida Simplificada: Permite programar el movimiento y las acciones una sola vez. El plugin traduce automáticamente si el jugador está usando la mitad de un teclado o un mando profesional.
- Gestión de Perfiles Nombrados: Los jugadores pueden crear, editar y guardar sus propios esquemas de controles (ej. "Perfil_Competitivo") que se mantienen guardados en el PC.
- Vibración Independiente y Segura: Envía efectos de vibración ("Rumble") únicamente al mando del jugador que realiza la acción, evitando crasheos o interferencias en otros dispositivos o teclados.
- Soporte de Doble Teclado: Permite que dos personas jueguen en un mismo teclado físico (uno con WASD y otro con las Flechas/Numpad) detectándolos como jugadores independientes. En Godot nativo, esto es extremadamente complejo de separar.
- Componentes de Prototipado Rápido: Incluye escenas listas para usar, como el "Modo Arcade", que permiten spawnear jugadores y probar tu gameplay en segundos.
Dicha configuración solo necesitas mandarla a llamar 1 sola vez al momento en el que inicie tu juego (_ready del Main o del Lobby).
Le diremos a nuestro AutoLoad qué acciones queremos registrar divididas en dos grandes grupos: Movimientos y Acciones Genéricas.
func _ready():
# 1. Definimos las direcciones de movimiento ESTRICTAMENTE en sentido Horario!
var movimientos = ["move_up", "move_right", "move_down", "move_left"]
# 2. Definimos nuestras acciones sueltas del estilo de juego
var acciones = ["jump", "attack", "interact", "dash"]
# 3. (Opcional) Puedes inyectar las teclas por defecto que quieras para tu juego.
var defaults_mov_teclado2 = [KEY_KP_8, KEY_KP_6, KEY_KP_5, KEY_KP_4] # Numpad
var defaults_act_teclado1 = [KEY_SPACE, KEY_X, KEY_E, KEY_SHIFT]
var defaults_act_mando = [JOY_BUTTON_A, JOY_BUTTON_X, JOY_BUTTON_Y, JOY_BUTTON_B]
# 4. Inicializamos Movimientos y Acciones por separado
if has_node("/root/InputMultiDevice"):
InputMultiDevice.setup_movements(movimientos, [], defaults_mov_teclado2)
InputMultiDevice.setup_actions(acciones, defaults_act_teclado1, [], defaults_act_mando)Note
Si no provees perfiles por defecto (parámetros opcionales), el plugin utilizará un mapeado genérico "Fallback" intentando asignar lógicamente tu lista a WASD / Flechas para movimientos, y a los botones principales para las acciones (A, B, X, Y, etc.).
Para un juego local, la forma más moderna de asignar mandos es a través de una escena Lobby o mediante un Modo Arcade (amigable y directo).
El plugin incluye una señal universal lista para capturar Start/Enter. Puedes escuchar esto en tu menú, asignarle el Dispositivo a un número de Jugador de tu preferencia, y aplicar un Perfil Nombrado de Input:
# Conectado a la señal InputMultiDevice.player_joined_lobby
func _on_player_joined(device_id):
var player_id = obtener_siguiente_libre_del_1_al_8()
# 1. Emparejamos física (Hardware) con lógica (Jugador)
InputMultiDevice.setup_player_device(player_id, device_id)
# 2. Le inyectamos su perfil de botones favorito (estilo Super Smash Bros)
InputMultiDevice.apply_custom_profile_to_player(player_id, "DANIEL_CUSTOM")Tip
En la carpeta addons/input_multi_device/scenes/ encontrarás el Modo Arcade, una demostración técnica Plug & Play incluida directamente en el plugin para que veas cómo spawnear jugadores al vuelo sin un Lobby complejo.
Cierra los ojos y olvídate del anticuado Input.is_action_pressed(). En tu clase de Personaje de aquí en adelante siempre consultarás la capa de InputMultiDevice, brindándole el ID del personaje:
var mi_player_id = 0 # (El jugador asignado a este PlayerNode)
func _physics_process(delta):
# Preguntar por acciones simples
if InputMultiDevice.is_action_pressed(mi_player_id, "jump"):
velocity.y = -400.0
if InputMultiDevice.is_action_just_pressed(mi_player_id, "attack"):
print("Toma golpe!")
# Preguntar por vectores armados (Ideal para mover tu KinematicBody!)
var dir = InputMultiDevice.get_vector(mi_player_id, "move_left", "move_right", "move_up", "move_down")
velocity.x = dir.x * SPEEDEl plugin maneja un banco de datos interno llamado custom_profiles. Al contrario de sobreescribir "player 1", este sistema emula el estándar actual de peleas guardando Perfiles Personalizados (Strings) que los jugadores pueden intercambiarse.
# 1. Crear un nuevo perfil clonando el layout de un Mando Base (Device = 0)
InputMultiDevice.create_custom_profile("Player_Pro", 0)
# 2. Escuchar un botón in-game para remapearlo en tu pantalla de Opciones
func _input(event):
if listening_for_input and event.is_pressed():
InputMultiDevice.remap_custom_profile("Player_Pro", "attack", event)
# 3. Eliminar perfiles basura
InputMultiDevice.delete_custom_profile("Player_Pro")Tip
Recuerda usar las plantillas protegidas del motor (Default_Mando, Default_Teclado_1, Default_Teclado_2) como bases inmutables para recuperar controles si alguien "rompe" su perfil durante el remapeo.
Por defecto, Godot aplica una zona muerta opaca de 0.5, pero en juegos de alta precisión esto puede ser muy tosco. El plugin inyecta por defecto una global_base_deadzone optimizada de 0.2 a todos los ejes creados.
Puedes brindarle un control (slider) a tus jugadores en las Opciones para ajustarlo dinámicamente:
InputMultiDevice.set_global_deadzone(0.15)Si necesitas que un botón actúe como un interruptor ("agacharse" vs "levantarse", "prender o apagar linterna"), en lugar de crear molestas variables internas de estado en tu personaje, delega el trabajo de rastreo al plugin usando este método en tu _physics_process:
# Cambiará entre 'true' y 'false' mágicamente cada vez que el jugador haga el "just_pressed" de la acción.
if InputMultiDevice.is_action_toggled(mi_player_id, "crouch"):
print("Modo sigilo activado")
else:
print("Modo normal")En Godot puro tienes que saber el Device ID del gamepad y programar condiciones if device >= 0 por todo tu código para no crashear los teclados virtuales. El plugin enruta esto automáticamente con total seguridad; si el jugador usa teclado, la orden hace bypass silencioso sin consumir recursos:
# Sintaxis: start_vibration(player_id, motor_debil, motor_fuerte, duracion_en_segs)
InputMultiDevice.start_vibration(mi_player_id, 0.5, 1.0, 2.0)
# Parar manualmente una vibración infinita
InputMultiDevice.stop_vibration(mi_player_id)Se ha integrado el script profile_persistence.gd diseñado para sortear la dificultad de serializar objetos InputEvent y transformarlos en formato encriptado de disco (CFG) a la ruta nativa y segura user://input_profiles.cfg sin ralentizar tu hilo principal.
# Simplemente llama a guardar cuando el jugador cierre el menú de mapeo de controles:
InputMultiDevice.save_profiles()
# Y llama a cargar en el _ready() de tu Juego o Menu Principal para restaurarlos:
InputMultiDevice.load_profiles()

