[Hack] WiiMote en Unity

Hace mucho tiempo que quería experimentar con el controlador de la Wii (WiiMote) en Unity y ayer me decidí a hacer la prueba.

Decepción

Mi primera decepción fue ver la poca variedad de plugins que existen para conectar un WiiMote a unity. Solo encontré dos proyectos: UniWii (OSX y Windows) y Wii Budy (OSX). La segunda decepción que, al ser plugins y no código fuente, es necesaria la versión Pro de Unity para poder utilizarlos. Dado que la versión Pro está de momento lejos de mi alcance, no me queda más remedio que darle al coco, así que empecé a devanarme la cabeza buscando un método que me permitiera al menos experimentar.

De todas formas si alguien tiene la fortuna de tener licencias Pro de Unity le recomiendo que le de una oportunidad a UniWii.

¡Python al rescate!

Hace unos años experimenté con una librería para python llamada python-cwiid que es en realidad un wrapper de cwiid pero “pitonisto”. Así que pensé… ¿cómo de loco/complicado sería hacer un programita en python que lea los datos del WiiMote y los sirva por la red a los clientes que se conecten? Dicho y hecho, me lié la manta a la cabeza y el resultado es un pequeño script que podéis encontrar en mi repositorio de GitHub: Python WiiMote Server

El script funciona conectándose al mando de Wii y esperando un cliente de red. Cuando recibe una conexión comienza a lanzar chorros de información sobre el estado del WiiMote. Para mis necesidades solo necesitaba la información de “Pitch & Roll“, por lo que no envío más datos, pero el script es fácilmente modificable para enviar la información que necesitemos.

Por la parte de Unity es muy simple: un script que haga la conexión TCP y procese la información a medida que llega. Como ya conocía algún ejemplo de esto, en lugar de empezar de cero me inspiré en el código de este chat para Unity. Podéis encontrar la versión funcional en mi repositorio de GitHub: Unity Client for pywiimoteserver

Más problemas

Este sistema funciona correctamente entre mis equipos: Unity en mi portátil con OSX y el servidor en mi PC con Ubuntu. El problema es que no es muy portable. No me veo llevando el PC por ahí para hacer pruebas… Así que en mi intento de poder enseñar por ahí este montaje recurrí a algo quizá un poco extremo pero que “A-Mi-Me-Funciona”(r): Montar una máquina virtual de Ubuntu en mi OSX con lo necesario para ejecutar mi script de python utilizando el adaptador Bluetooth del portátil. Para ello utilicé VirtualBox y una ISO de Ubuntu 12.04 LTS de 32 bits.

El gran problema con ésta aproximación es que VirtualBox no puede asignar el dispositivo Bluetooth a la máquina invitada (hay un ticket abierto sobre esto desde hace más de 5 años…). Por suerte en el mismo hilo del ticket alguien ofrece una solución que transcribo a continuación:

1) Deshabilitar Bluetooth desde un terminal como root:

launchctl unload /System/Library/LaunchDaemons/com.apple.blued.plist

# En Mountain Lion:

kextunload -b com.apple.iokit.IOBluetoothSerialManager

kextunload -b com.apple.iokit.BroadcomBluetoothHCIControllerUSBTransport

# En Snow Leopard

kextunload -b com.apple.driver.BroadcomUSBBluetoothHCIController

#kextunload -b com.apple.driver.AppleUSBBluetoothHCIController

2) Arrancar la máquina virtual (VirtualBox en nuestro caso)

3) Asignar el dispositivo USB Apple Inc. Bluetooth USB Host Controller al guest.
4) ¡Disfrutar!

Para recuperar el Bluletooth en nuestro sistema original, tras cerrar la máquina 
virtual, de nuevo como root:

launchctl load /System/Library/LaunchDaemons/com.apple.blued.plist

# En Mountain Lion

kextload -b com.apple.iokit.IOBluetoothSerialManager

kextload -b com.apple.iokit.BroadcomBluetoothHCIControllerUSBTransport

# En Snow Leopard

kextload -b com.apple.driver.BroadcomUSBBluetoothHCIController

kextload -b com.apple.driver.AppleUSBBluetoothHCIController

Es un poco pesado, pero obviamente tengo un par de scripts que me lo hacen solo. Lo más importante es que este workaround me permite ejecutar mi máquina virtual, usar el bluetooth del portátil, conectar el mando de Wii y utilizarlo con Unity sin necesidad de usar plugins (y por lo tanto Unity Pro) ni tener que transportar el PC conmigo :D

Alguien se preguntará por qué no ejecuto el servidor python directamente en OSX. La respuesta es que python-cwiid no funciona en OSX y no he encontrado ninguna librería lo suficiéntemente cómoda como para cambiar. Existe WiiUse, pero requiere un parche para funcionar en OSX y además en mis pruebas se han producido varios errores de violación de segmento que no me dan confianza. Otra opción sería conectar directamente con el mando utilizando lightblue que funciona en OSX y en teoría también en Linux y Windows, pero no quiero echarle más tiempo a esto. Además lightblue está por desgracia descontinuado… Si tenéis curiosidad por ver una implementación con lightblue, podéis consultar este post: Prototyping with Wii Remotes in Python

Si alguien se pregunta si el sistema es lento por ser a través de la red, he de decir que no mucho. El servidor envía en teoría unos 60 eventos por segundo y en el cliente se nota bastante fluido y sin apenas retraso. Creo recordar que el WiiMote reporta a 100Hz (100 por segundo) así que creo que está bastante bien.

Por último, si queréis ver el sistema en funcionamiento, aquí tenéis éste vídeo:

!Gracias por leer hasta aquí! ¡Si os es útil, dejadme un comentario!

Un pensamiento en “[Hack] WiiMote en Unity

Dime algo...